C++ 一条语句中的多个复合赋值:是否为未定义行为?

C++ 一条语句中的多个复合赋值:是否为未定义行为?,c++,c++11,undefined-behavior,C++,C++11,Undefined Behavior,我找不到一个明确的答案:下面的代码是否有未定义的行为 int x = 2; x+=x+=x+=2.5; 该行为未定义。让我们看看稍微简单一点的表达式: x += (x+=1) 在C++11中,左x的值计算相对于表达式(x+=1)的值计算是不排序的。这意味着x的值计算相对于x的赋值不排序(由于x+=1),因此行为未定义 这是因为+=运算符两侧的值计算是相对不排序的(因为标准没有另行规定)。和1.9p15说明: 如果标量对象上的副作用相对于同一标量对象上的另一副作用或使用同一标量对象的值进行的值

我找不到一个明确的答案:下面的代码是否有未定义的行为

int x = 2;
x+=x+=x+=2.5;

该行为未定义。让我们看看稍微简单一点的表达式:

x += (x+=1)
在C++11中,左
x
的值计算相对于表达式
(x+=1)
的值计算是不排序的。这意味着
x
的值计算相对于
x
的赋值不排序(由于
x+=1
),因此行为未定义

这是因为
+=
运算符两侧的值计算是相对不排序的(因为标准没有另行规定)。和1.9p15说明:

如果标量对象上的副作用相对于同一标量对象上的另一副作用或使用同一标量对象的值进行的值计算未排序,则该行为未定义


在C++03中,行为是未定义的,因为
x
被修改了两次,没有插入序列点。

有关标准引号,请参见其他答案。在这种情况下,可能会发现两种不同的行为之一

x += (x += 2);
可能是

x = 2 + 4 (= 6)
如果在
x+=2
之前计算左侧的x值,或

x = 4 + 4 (= 8)
如果随后确定左运算符的x值


-编辑-

我知道我不会吸引很多粉丝,所以如果我说我不喜欢那些“任何事情都有可能发生”的说法。 的确,任何编译器都可以声明自己符合标准,而不管我们在这里讨论的语句是如何处理x值的。然而,我认为这并不意味着运算符+=可能导致错误的结果,或者可以忽略偏执。 未定义的行为与任何其他情况下的未定义行为不同

对于未定义的行为,放弃任何期望是不好的,但是在上面的例子中,我看到了忽略任何可能结果的好理由,除了6和8

此外,在计算
intx=2之后,我实际上怀疑x是8;x+=(x+=2)适用于大多数已建立的编译器(clang、g++、vc、icpc…)


需要再次指出的是,你不应该依赖这种行为,但这并不意味着它是完全不可预测的。

这不是重复。这里的表达式是
x++=(x++=10)
,它不同于
(x++=10)+=10
——这里的行为是未定义的,而另一个问题不是(在c++11中)。我上面的评论指的是以前标记为重复的问题。你为什么真的想知道?Alex,如果这个问题是我的话。我在面试中也遇到了类似的问题,我不确定这个问题是否没有定义。显然,没有人会在实际代码中使用此示例。这里可能会出现至少两种行为。行为是未定义的,因此枚举可能的行为是一项无休止的任务。显示至少存在两种不同的结果(通过矛盾显示)与枚举是有区别的。对于案例2,它们是相同的。允许优化编译器假定程序的行为不是未定义的。如果您违反了该假设,他们可以执行违反您假设的转换。在任何情况下,
x+=(x+=2)的方式并不重要行为;不管它是什么意思,都有一种更清晰的表达方式。注意:如果
x
是一个对象,带有用户定义的
操作符+=
,那么它将被定义…很抱歉先对其进行了否决。正如你在对这个问题的评论中所解释的,这两种表达方式是不同的,你的答案确实是完全正确的+1.