Dar*_*usz 11 c++ variable-assignment expression-evaluation operator-precedence c++11
C++ 11标准(5.17,expr.ass)表明了这一点
在所有情况下,在右和左操作数的值计算之后,以及在赋值表达式的值计算之前,对赋值进行排序.对于不确定序列的函数调用,复合赋值的操作是单个评估
据我了解,作为给定赋值的一部分的所有表达式将在赋值本身之前进行求值.即使我在同一个赋值中修改了两次相同的变量,这条规则也应该有效,我相当肯定,之前是未定义的行为.
请问代码:
int a = 0;
a = (a+=1) = 10;
if ( a == 10 ) {
printf("this is defined");
} else {
printf("undefined");
}
Run Code Online (Sandbox Code Playgroud)
总是评价到a==10?
是的,C++ 98和C++ 11之间发生了变化.我相信你的例子在C++ 11规则下定义良好,同时在C++ 98规则下表现出未定义的行为.
作为一个更简单的例子,x = ++x;在C++ 98中未定义,但在C++ 11中定义良好.注意x = x++;仍然是未定义的(后增量的副作用在表达式的评估中未被测序,而预增量的副作用在相同之前被排序).
让我们重写您的代码
E1 = (E2 = E3)
Run Code Online (Sandbox Code Playgroud)
其中E1是表达式a,E2是表达式a += 1,E3是表达式10.在这里我们使用了,赋值运算符从右到左分组(C++ 11标准中的§5.17/ 1).
§5.17/ 1此外还说明:
在所有情况下,在右和左操作数的值计算之后,以及在赋值表达式的值计算之前,对赋值进行排序.
将此应用于我们的表达式意味着我们首先必须评估子表达式E1和E2 = E3.请注意,这两个评估之间没有"按顺序排序"关系,但这不会导致任何问题.
id表达式 的评估E1是微不足道的(结果a本身).赋值表达式 的评估过程E2 = E3如下:
首先必须评估两个子表达式.文字 的评价E3再次微不足道(给出了价值10的初值).
(化合物)赋值表达式 的评估E2在以下步骤中完成:
1)行为a += 1相当于a = a + 1但a只评估一次(§5.17/ 7).在评估子表达式a和1(以任意顺序)之后,应用左值到右值的转换a以读取存储的值a.
2)a(是0)和的值()1(a + 1)和这个加法的结果是值的初始值1.
3)在我们计算赋值结果之前a = a + 1,左操作数引用的对象的值被右操作数的值(§5.17/ 2)替换.然后结果E2是左值引用新值1.请注意,在赋值表达式的值计算之前,会对副作用(更新左操作数的值)进行排序.这是上面引用的§5.17/ 1.
现在我们已经评估了子表达式,E2并且E3表达式E2引用的值被替换为值E3,即10.因此结果E2 = E3是价值的左值10.
最后,值表达式E1引用被表达式的值替换E2 = E3,我们计算得到它10.因此,变量a最终包含该值10.
由于所有这些步骤都是明确定义的,因此整个表达式产生了明确定义的值.