在VS2008中,"<<和++"的运算符优先级与优化相关。

9
我是一名有用的助手,下面是您需要翻译的内容:

我遇到了一个奇怪的VS2008 C++问题,看起来好像运算符优先级没有被尊重。

我的问题是这个代码会输出什么:

int i = 0;  
std::cout << ((i != 0) ? "Not zero " : "zero ") << ++i << std::endl;  

通常情况下,++的优先级高于<<,对吗?还是说<<被视为函数调用,使其优先级高于++?这个问题的100%正确标准答案是什么?
为了验证,我创建了一个新的空项目(VS2008控制台应用程序),将此代码粘贴到主函数中,以下是结果:
Debug|Win32: “zero 1”  
Release|Win32: “zero 1”  
Debug|x64: “zero 1”  
Release|x64: “Not zero 1”

顺便说一下,以下示例产生完全相同的结果:
i = 0;  
printf("%s %d\n", ((i != 0) ? "Not zero" : "zero"), ++i);  

同时,在发布中更改优化类型没有效果,但禁用优化会像其他配置一样输出“zero 1”。


函数参数的评估顺序是未指定的,这就解释了你的第二个例子。我想第一个片段也是同样的情况。 - Pedro d'Aquino
1
如果您能够在根本没有使用<<运算符的情况下获得相同的意外输出,那么为什么您要将这个问题框定为<<++之间的优先级相关呢? - Rob Kennedy
1个回答

18

这与运算符优先级无关。
你正在使用 << 这个语法糖来进行函数调用:

std::cout << ((i != 0) ? "Not zero " : "zero ") << ++i << std::endl; 

// Equivalent to:

operator<<(operator<<(operator<<(std::cout, ((i != 0) ? "Not zero " : "zero ")), ++i), std::endl);

这里唯一的规则是在函数调用之前必须完全评估参数。对于参数的评估顺序没有限制,即使它们的评估与调用交错(甚至部分评估)也没有限制。

解释 1:

这句话的意思是,在函数被调用之前,参数必须被完全评估。虽然参数评估的顺序没有限制,但可以交替或部分地进行评估,而且不会造成任何问题。
1) ((i != 0) ? "Not zero " : "zero "))
2) ++i
3) operator<<(std::cout, (1));
4) operator<<((3), (2));
5) operator<<((4), std::endl);

注意:限制如下:

 A) (1) happens before (3)
 B) (2) happens before (4)
 C) (3) happens before (4)
 D) (4) happens before (5)

鉴于这些限制,我们可以按照如下顺序重新排列。

解释2:

1) ++i
2) ((i != 0) ? "Not zero " : "zero "))
3) operator<<(std::cout, (2));
4) operator<<((3), (1));
5) operator<<((4), std::endl);

解释 3:

1) ((i != 0) ? "Not zero " : "zero "))
2) operator<<(std::cout, (1));
3) ++i
4) operator<<((2), (3));
5) operator<<((4), std::endl);

s/Equivalent too/Equivalent to/ 。并+1 :) - Billy ONeal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接