为什么把一个函数的return值乘以零,它不会短路?
Why doesn't it short-circuit when you multiply the return value of a function by zero?
考虑如下函数:
unsigned int fact(unsigned int i) {
if (i <= 1) { return 1; }
return i * fact(i-1);
}
如果我要实例化一个新变量 unsigned int f
使得 f = 0 * fact(5)
,为什么它不 "short circuit"?
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);
}
这里的输出是aaaaa
。如果 f
只能为零,为什么它会调用函数,假设它知道 return 类型?它不是从左到右评估吗,请参阅 0 * (unsigned int)
并知道右值将是 0
?
短路评估对于 &&
(逻辑 和 )、||
(逻辑 或 是强制性的) 和 ?
(三元运算符)。对于其余的运算符,这是一个(可选的)优化。
表达式 0 * fact(5)
中 fact(5)
的求值一般不能被优化掉,因为你知道整个表达式的结果是 0
因为调用fact()
可能会引入副作用(例如,修改一些全局变量),所以必须调用它。
正如 中所说,如果可以证明没有副作用,一个好的编译器会优化对 fact(5)
的调用。
Does it not evaluate left to right, see 0 * (unsigned int) and know the rvalue will be 0?
它可以,而且如果标准要求它会这样做。
但事实并非如此。
短路根本不是乘法的事情。他们本可以让它成为一件事,但可以说它会让人感到困惑。
我们都习惯于 f() || g()
可能会跳过对 g()
的调用,但您真的希望 0 * g()
做同样的事情吗?特别是因为 0
只是 十亿 可能整数中的一个?这将是一个奇怪的特定功能。 (相比之下,true
是两个布尔值中的一个。)
这与副作用无关,因为 g()
的副作用会被 f() || g()
如果 f()
returns true
跳过。就是这样。
实际上,编译器可以在0 * g()
中省略对g()
的调用,如果它知道g()
没有副作用的话(所以程序的行为不会改变),但这不是短路;那是 .
考虑如下函数:
unsigned int fact(unsigned int i) {
if (i <= 1) { return 1; }
return i * fact(i-1);
}
如果我要实例化一个新变量 unsigned int f
使得 f = 0 * fact(5)
,为什么它不 "short circuit"?
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);
}
这里的输出是aaaaa
。如果 f
只能为零,为什么它会调用函数,假设它知道 return 类型?它不是从左到右评估吗,请参阅 0 * (unsigned int)
并知道右值将是 0
?
短路评估对于 &&
(逻辑 和 )、||
(逻辑 或 是强制性的) 和 ?
(三元运算符)。对于其余的运算符,这是一个(可选的)优化。
表达式 0 * fact(5)
中 fact(5)
的求值一般不能被优化掉,因为你知道整个表达式的结果是 0
因为调用fact()
可能会引入副作用(例如,修改一些全局变量),所以必须调用它。
正如 fact(5)
的调用。
Does it not evaluate left to right, see 0 * (unsigned int) and know the rvalue will be 0?
它可以,而且如果标准要求它会这样做。
但事实并非如此。
短路根本不是乘法的事情。他们本可以让它成为一件事,但可以说它会让人感到困惑。
我们都习惯于 f() || g()
可能会跳过对 g()
的调用,但您真的希望 0 * g()
做同样的事情吗?特别是因为 0
只是 十亿 可能整数中的一个?这将是一个奇怪的特定功能。 (相比之下,true
是两个布尔值中的一个。)
这与副作用无关,因为 g()
的副作用会被 f() || g()
如果 f()
returns true
跳过。就是这样。
实际上,编译器可以在0 * g()
中省略对g()
的调用,如果它知道g()
没有副作用的话(所以程序的行为不会改变),但这不是短路;那是