<基于 C++ Primer P123>
1.求值顺序 & 优先级 & 结合律:
对于:f( ) + g( ) * h( ) + j( )
(1)优先级规定:g( ) 的返回值于 h( ) 的返回值相乘。
(2)结合律规定:f( ) 的返回值先于 g( ) 和 h( ) 的乘积相加,随后与 j( ) 的返回值相加。
(3)对于这些函数的调用顺序没有规定。
因此,若其中某几个函数影响同一对象,就是一条错误的表达式,将产生未定义的行为。
2.另外三个例子:
(1)
int i = f1() * f2();
f1( ) 和 f2( ) 一定会在执行乘法之前被调用,但无法知道 f1 是在 f2 之前调用还是在 f2 之后调用。
(2)
int i = 0;
cout << i << " " << ++i << endl;
此表达式的行为是不可预知的。
(3)
while (beg != s.end() && !isspace(*beg))
*beg = toupper(*beg++); // 错误:该赋值语句未定义
编译器可能按照下面的任意一种思路处理该表达式(也可能采取别的什么方式处理)
*beg = toupper(*beg); // 先求左侧的值
*(beg + 1) = toupper(*beg); // 先求右侧的值
3.四个规定了运算对象求值顺序的运算符:
(1)&&:先求左侧运算对象的值,左为真时求右侧运算对象的值。
(2)| |:先求左侧运算对象的值,左为假时求右侧运算对象的值。
(3)?::先求 cond 的值,若条件为真对 expr1 求值并返回该值;若条件为假对 expr2 求值并返回该值。
(4),:从左向右依次求值。
4.经验准则:
C++只规定了非常少的二元运算符的求值顺序,这样做提高了代码生成的效率,但是可能引发潜在的缺陷。
(1)使用括号强制让表达式的组合关系符合程序逻辑的要求。
(2)如果改变了某个运算对象的值,在表达式的其他地方不要再使用这个运算对象。
例外:*++iter,递增运算必须先求值,再轮到解引用运算。