res + =(f(i),f(i + 1)),f(i + 2)是什么?评估为?
#include <iostream>
int f(int x)
{
static int cnt = 0;
return ++cnt * x;
}
int main ()
{
int res = 0;
for (int i = 0; i < 6; ++i) {
res += (f(i), f(i + 1)), f(i + 2);
// f(i);
// res += f(i + 1);
// f(i + 2);
std::cout << res << std::endl;
}
std::cout << res;
}
我不知道这行是如何工作的:
res += (f(i), f(i + 1)), f(i + 2);
我知道它等同于被注释的部分,但是为什么呢?
答案 0 :(得分:6)
此答案说明了您使用此表达式观察到的行为:
res += (f(i), f(i + 1)), f(i + 2);
...但是我建议您不要在任何生产代码中使用此代码,出于某些原因,请参阅答案的结尾。
在表达式中使用时,逗号,
对应于标准操作符comma operator:
// Evaluate E1 then E2, discards the result of E1, return E2
E1, E2
+=
运算符也是一个运算符,其优先级比,
(,
的优先级在C ++中最低),因此:
int f();
int g();
int x = 0;
// Equivalent to:
// x += f();
// g();
x += f(), g();
// Equivalent to:
// f();
// x += g();
x += (f(), g());
在您的情况下,您需要用一对圆括号括住前两个调用:
res += (f(i), f(i + 1)), f(i + 2);
// ^--------------^
所以:
f(i), f(i + 1)
被评估(由于括号),这导致调用f(i)
然后 f(i + 1)
,并存储f(i + 1)
的结果在临时; res
运算符添加到+=
; res += (f(i), f(i + 1))
的结果将被丢弃; f(i + 2)
被评估。如注释中所指定,此代码等效于:
f(i);
res += f(i + 1);
f(i + 2);
编译器无法删除对f(i)
和f(i + 1)
的调用,因为它们具有副作用(static
变量cnt
的更新)。
我建议不要出于此类原因而使用逗号运算符,主要是出于清楚的原因:
f
返回一个类似big_int
的类,则不能保证operator,
的操作数的求值顺序。从C ++ 17开始,您会获得fold expressions的逗号运算符,这是使用逗号运算符的很少原因之一。