赋值子表达式的评估顺序

时间:2013-10-25 09:16:43

标签: c++ c++11 variable-assignment operator-precedence

The C++11 standard(5.17,expr.ass)声明

  

在所有情况下,在计算值之后对赋值进行排序   左右操作数,以及值的计算之前   赋值表达式。关于   不确定顺序的函数调用,化合物的操作   赋值是一个单一的评估

这是否意味着表达式:

int a = 1, b = 10;
int c = (a+=1) + (b+=1);

if ( c == 10+1+1+1 ) {
    printf("this is guaranteed");
} else {
    printf("not guaranteed"); 
}

将始终评估为c==23

3 个答案:

答案 0 :(得分:2)

表达式

int c = (a+=1) + (b+=1);

(编辑:添加了缺少的括号,我认为这是你的意图)

具有以下子表达式

(1) a+=1
(2) b+=1
(3) (1)+(2)
(4) c = (3)

未指定评估(1)和(2)的顺序,编译器可以自由选择它喜欢的任何顺序。

编译器可以在评估之前评估(1)和(2)。

(3)必须在之前进行评估编译器可以评估(4)。

现在,由于(1)和(2)的评估顺序无关紧要,整体结果已明确定义,您的代码将始终生成13并打印“这是现在的标准”。请注意,这一直是这样,这对于C ++ 11来说并不新鲜。

答案 1 :(得分:1)

在您的示例中,编译器应发出错误,因为加法运算符的优先级高于赋值运算符的优先级。因此,首先计算1 + b,然后尝试将1分配给表达式(1 + b),但(1 + b)不是左值。

答案 2 :(得分:1)

这始终得到保证,并且在规则之前排序 (或者在C ++ 11之前的序列点规则)不需要 确定这个。在C ++中,每个(子)表达式都有两个重要的表达式 生成的代码中的效果:它有一个值(除非它是 键入void),它可能有副作用。按顺序排列 之前/序列点规则会影响副作用 保证已经发生;它们对价值没有影响 子表达式。在您的情况下,例如, (a += 1)的{​​{1}}是赋值后的a值, 无论实际分配何时发生。

在C ++ 11中,保证a的实际修改 修改c之前的地方;在预C ++ 11中,没有 关于订单的保证。然而,在这种情况下,存在 合规程序无法看到这种差异,所以它 无所谓。 (在像c = (c += 1)这样的情况下,这很重要, 这在前C ++ 11中将是未定义的行为。)