我通过引用调用以下列方式定义的阶乘函数。
int factorial(int &n) {
n--;
if (n>0) return factorial(n)*(n+1);
else return 1;
}
当我传递值 5 时,它会按我的预期返回值 1。但是,当我按以下方式定义阶乘函数时,它会返回 5 的阶乘,即 120。
int factorial(int &n) {
n--;
if (n>0) return (n+1)*factorial(n);
else return 1;
}
我推测表达式是按线性顺序求值的,当在表达式中调用函数时,存储到目前为止在原始表达式中求值的所有局部变量和组件表达式的值,并且当函数返回控制权时返回给调用者,这些保留的值用于表达式的计算,而不是它们的修改值。
我的假设是否正确?请赐教。
最佳答案
I conjectured that the expression is evaluated in linear order [...]
是也不是。评估顺序通常按线性顺序进行(先到后或后到先),但未指定。当您编写 factorial(n)*(n+1)
时,允许编译器首先评估 (n+1)
或 factorial(n)
第一。不同的编译器会做不同的事情。此外,同一个编译器的不同版本甚至可以改变顺序,所以这不是你应该依赖的东西。标准语在 [intro.execution] :
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...] If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined.
(异常(exception)情况是 &&
、||
、、
和 ?:
)
在这种情况下,只需删除引用即可轻松避免完全依赖顺序依赖:
int factorial(int n) {
if (n>0) return factorial(n-1)*(n);
else return 1;
}
现在,factorial(n-1) * n
和 n * factorial(n-1)
,无论它们的计算顺序如何,都可以工作并给出你同样的正确答案。这还有一个额外的好处,即没有人会期望 factorial
无论如何都会实际修改它的参数:
int i = 6;
int f = factorial(i);
// now i is 1??
关于c++ - 为什么在更改赋值语句中的顺序时代码的实现方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36133311/