c++求值顺序的重要性

说明 文章中红色下划线字体表示我认为比较重要的知识点。
内容 优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么样的顺序求值。在大多数情况下,不会明确指定求值的顺序,对于如下表达式:
int i = f1() * f2()。//想象如果f1和f2都引用了一个全局对象,并对其进行了相应的操作,那么将会引发灾难
我们知道f1和f2一定会在执行乘法之前被调用,因为毕竟相乘的是两个函数的返回值。但是我们无法确定f1在f2之前运行还是f2在f1之前运行。
对于那些没有指定执行顺序的的运算符来说,如果表达式修改的是同一个对象,将会引发错误并产生未定义的行为。
举个例子:
<<运算符乜有明确规定何时以及如何对运算对象求值,因此下面的表达式是未定义的。

int i = 0; cout << i << ' ' << i++ << endl;

因为程序时未定义的,所以我们无法推断出它的行为。编译器可能先求出++i的值再求i的值,也可能先求i的值再求i++的值,甚至编译器可能做出完全不同的操作,因此此表达式的行为时未知的。
实际的测试结果:
g++ -Wall demo2.cpp
编译时提示的警告信息:
demo2.cpp: In function ‘int main()’: demo2.cpp:15:23: warning: operation on ‘i’ may be undefined [-Wsequence-point] cout << i << ' ' << i++ << endl;

执行结果
0 0
注意:有四种运算符明确规定了运算对象的求值顺序:
逻辑与(&&)、逻辑或(||)、条件表达式(? : )、逗号表达式(,)
总结:因此我们在写程序时一定要注意表达的求值顺序对程序的影响,必须规避这种程序设计,保证程序的时序是可控的。
参考文献:
【c++求值顺序的重要性】c++ primer 第5版。

    推荐阅读