C++和Java中表达式求值顺序有何不同?

9
我曾经试图理解这个页面上的示例,让我的大脑感到困惑: http://answers.yahoo.com/question/index?qid=20091103170907AAxXYG9 更具体地说,是这段代码:
int j = 4;
cout << j++ << j << ++j << endl;

输出结果为:566。

如果表达式从右到左计算,那么这对我来说是有意义的。然而,在Java中,类似的表达式:

int j = 4;
System.out.print("" + (j++) + (j) + (++j));

输出结果为:456。

这更直观,因为它表明已从左到右进行了评估。在各种网站上进行研究后,似乎在C++中,行为在编译器之间有所不同,但我仍然没有被说服理解这种差异的原因。Java和C++之间的这种评估差异的解释是什么?谢谢SO。


2
一切都是不同的。这不仅在编译器之间不同,而且违反规则,并且每次在同一编译器上编译、运行程序或甚至每次执行该行时都可能发生变化。 - Mooing Duck
可能是未定义行为有多未定义?的重复问题。 - Mooing Duck
1
C++旨在进行优化,这意味着标准不保证特定的结果,因此编译器可以自由生成最佳代码。您在示例中使用的序列是我认为明确禁止的。 - Mark Ransom
@MarkRansom:它并不是被禁止的...只是它的结果未定义 :) - user405725
3个回答

11
当操作具有副作用时,C++ 依赖于序列点规则来决定何时执行副作用(如增量、组合赋值等)。逻辑and-then/or-else(&&||)运算符、三元?问号运算符和逗号创建序列点;+-<<等则不会。
相比之下,Java在继续评估之前完成了副作用。
如果您在没有序列点的情况下多次使用具有副作用的表达式,则在 C++ 中其结果行为是未定义的。任何结果都是可能的,包括不合乎逻辑的结果。

5

Java保证运算符的操作数按照从左到右的顺序进行评估。在评估二元运算符的左操作数时,似乎完全评估左操作数之前才会评估右操作数的任何部分。Java还保证,在执行任何操作本身的任何部分之前,操作符的每个操作数(除了条件操作符&&, ||, 和 ?:)都似乎已经被完全评估。有关更多详细信息,请参阅Java语言规范§15.7。

另一方面,C++却可以让你在表达式不明确时获得未定义行为,因为语言本身不保证子表达式的任何评估顺序。请参考Sequence Point以获取更多详细信息。


3

C++中子表达式的评估顺序既不是从左到右,也不是从右到左。这是未定义的


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