1

C++11 标准(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?

4

3 回答 3

2

表达方式

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

(编辑:添加缺少的括号,我认为这是你想要的)

有以下子表达式

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

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

(1) 和 (2) 都必须在编译器评估 (3)之前进行评估。

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

现在,由于 (1) 和 (2) 的评估顺序无关紧要,总体结果已经很好地定义,您的代码将始终产生13并打印“这现在是标准的”。请注意,一直都是这样,这在 C++11 中并不新鲜。

于 2013-10-25T09:23:40.817 回答
1

这一直是有保证的,并且不需要先排序规则(或 C++11 之前的顺序点规则)来确定这一点。在 C++ 中,每个(子)表达式在生成的代码中都有两个重要的影响:它有一个值(除非它是 类型void),它可能有副作用。顺序的前/顺序点规则影响副作用何时发生;它们对子表达式的值没有影响。例如,在您的情况下,无论实际分配何时发生,赋值后的 都是(a += 1)值。a

在 C++11 中,a保证 的实际修改发生在 ; 的修改之前c。在 C++11 之前,没有关于订单的保证。但是,在这种情况下,符合标准的程序无法看到这种差异,所以没关系。(在类似的情况下很重要c = (c += 1),这在 C++11 之前是未定义的行为。)

于 2013-10-25T10:06:54.387 回答
1

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

于 2013-10-25T09:27:37.853 回答