优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么样的顺序求值。在大多数情况下,不会明确指定求值的顺序,对于如下表达式:
int i = f1() * f2()。//想象如果f1和f2都引用了一个全局对象,并对其进行了相应的操作,那么将会引发灾难。
我们知道f1和f2一定会在执行乘法之前被调用,因为毕竟相乘的是两个函数的返回值。但是我们无法确定f1在f2之前运行还是f2在f1之前运行。
对于那些没有指定执行顺序的的运算符来说,如果表达式修改的是同一个对象,将会引发错误并产生未定义的行为。
举个例子:
<< 运算符没有明确规定何时以及如何对运算对象求值,因此下面的表达式是未定义的。
int i = 0;
cout << i << ' ' << i++ << endl;
因为程序时未定义的,所以我们无法推断出它的行为。编译器可能先求出++i的值再求i的值,也可能先求i的值再求i++的值,甚至编译器可能做出完全不同的操作,因此此表达式的行为时未知的。
实际的测试结果:
VS2017 [Release]
执行结果
0 0
VS2017 [Debug]
执行结果
1 0
注意:有四种运算符明确规定了运算对象的求值顺序:
逻辑与(&&)、逻辑或(||)、条件表达式(? : )、逗号表达式(,)
总结:因此我们在写程序时一定要注意表达的求值顺序对程序的影响,必须规避这种程序设计,保证程序的时序是可控的。