c++ - 为什么在更改赋值语句中的顺序时代码的实现方式不同?

标签 c++ recursion

我通过引用调用以下列方式定义的阶乘函数。

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) * nn * factorial(n-1),无论它们的计算顺序如何,都可以工作并给出你同样的正确答案。这还有一个额外的好处,即没有人会期望 factorial 无论如何都会实际修改它的参数:

int i = 6;
int f = factorial(i);
// now i is 1??

关于c++ - 为什么在更改赋值语句中的顺序时代码的实现方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36133311/

相关文章:

javascript - 循环内的 VueJS 组件充当一个整体

javascript - 如何仅在递归完成后才进行 Promise 解析?

c++ - 将 "unsigned char *"转换为 "char *"(和字符串)

c++ - 使用大型系统的编程模板

c++ - AVR ATMega169P 液晶显示器使用 C++

javascript - 我的程序适用于 array::forEach 但不适用于 for 循环

c++ - 仅使用递归来提取c++中 vector 中的最大元素

swift - 具有基于递归关系的条件的 NSPredicate - Swift - 核心数据

c++ - GTKMM:如何将键盘事件附加到绘图区域?

c++ - 如何在 C/C++ 中为其变量之一定义一个函数,该函数可以同时处理 int 和 long int?