我通过引用调用以下方式定义的阶乘函数.
int factorial(int &n) {
n--;
if (n>0) return factorial(n)*(n+1);
else return 1;
}
Run Code Online (Sandbox Code Playgroud)
当我传递值5时,它返回值1,正如我所期望的那样.但是当我以下面的方式定义阶乘函数时,它返回5的阶乘,即120.
int factorial(int &n) {
n--;
if (n>0) return (n+1)*factorial(n);
else return 1;
}
Run Code Online (Sandbox Code Playgroud)
我推测表达式是按线性顺序计算的,当在表达式中调用一个函数时,存储局部变量的所有值和到目前为止在原始表达式中已经计算过的组件表达式,并且当函数将控制权返回给调用者这些保留的值用于计算表达式而不是它们的修改值.
我的假设是否正确?请赐教.
Bar*_*rry 10
我推测表达式是按线性顺序评估的[...]
是的,不是.评估顺序通常以线性顺序(从第一个到最后一个或从最后一个到第一个)完成,但未指定.编写时factorial(n)*(n+1),允许编译器(n+1)首先或factorial(n)首先进行评估.不同的编译器将采用不同的方式.而且,同一编译器的不同版本甚至可以改变排序,因此这不是你应该依赖的东西.标准是[intro.execution]:
除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的评估是不确定的.[...]如果对标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值进行的值计算未被排序,并且它们不可能并发(1.10),则行为未定义.
(唯一的例外是一样的东西&&,||,,,和 ?:)
在这种情况下,只需删除引用即可轻松完全依赖于顺序依赖:
int factorial(int n) {
if (n>0) return factorial(n-1)*(n);
else return 1;
}
Run Code Online (Sandbox Code Playgroud)
现在factorial(n-1) * n和n * factorial(n-1),无论哪个秩序的他们评估了,工作和给你同样的正确答案.这也有额外的好处,没有人会期望factorial实际修改它的论点:
int i = 6;
int f = factorial(i);
// now i is 1??
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
144 次 |
| 最近记录: |