为什么将函数的返回值乘以零时不会短路?

gat*_*tor 3 c++ return lazy-evaluation short-circuiting

考虑如下函数:

unsigned int fact(unsigned int i) {
    if (i <= 1) { return 1; }
    return i * fact(i-1);
}
Run Code Online (Sandbox Code Playgroud)

如果我要实例化一个新变量unsigned int f,那么f = 0 * fact(5)为什么它不会“短路”?

unsigned int fact(unsigned int i) {
    std::cout << "a";
    if (i <= 1) { return 1; }
    return i * fact(i-1);
}

int main() {
    unsigned int f = 0 * fact(5);
}
Run Code Online (Sandbox Code Playgroud)

这里的输出是aaaaa。如果f只能为零,为什么它会调用该函数,假设它知道返回类型?它不评估从左到右,看到0 * (unsigned int)并知道右值将是0

眠りネ*_*ネロク 7

对于&&(逻辑)、||(逻辑)和?(三元运算符),短路评估是强制性的。对于其余的运算符,它是一个(可选的)优化。

fact(5)表达式中的的评估0 * fact(5)通常不能被优化掉,因为您知道整个表达式的结果是0因为调用fact()可能会引入副作用(例如,修改某些全局变量),因此必须调用它。

正如在这条评论中所说,一个好的编译器会优化掉对的调用,fact(5)如果它可以证明没有副作用。

  • 关于副作用的讨论有点分散注意力,因为无论副作用如何,都可以省略短路的“||”/“&amp;&amp;”操作数。 (3认同)
  • 如果一个好的编译器能够证明它没有副作用,它就会省略对“fact”的调用。例如,对于 OP 的示例,如果删除了“cout”,GCC 就会这样做。 (2认同)