让我们举个例子来说明特定的复合赋值运算符^=
。 This stackoverflow page表示在评估^=
之后可能尚未对左操作数进行修改,从而使代码a ^= b ^= a ^= b
未定义为行为。但事实似乎并非如此。标准在5.17 [expr.ass]中说
在所有情况下,在计算值之后对赋值进行排序 左右操作数,以及值的计算之前 赋值表达式。
本声明中有两个关键点。 1)主题赋值是指什么?在我看来,它仅指左操作数的修改。 2)赋值表达式的值计算是指什么? cppreference表示它返回对已修改对象的引用(强调我的)。
作为结论,在评估^=
之后,左操作数应该已经被修改,这与大多数人的想法相矛盾。我在这里错过了什么吗?
答案 0 :(得分:2)
您链接到C问题。但是,这是无关紧要的,因为C和C ++是不同的语言。
此外,从C11和C ++ 11开始,序列点不再存在;相反,在,未序列和不确定序列之前,关系已经排序。
在那句话中:
a
的内存位置。2 + 2
的值为4
,值计算是确定4
是值的过程。这里有两个值计算:a ^ b
和a =
(结果)。
在引用的文字中,对于a = a ^ b
,事情必须按此顺序发生:
从a
和b
(以任意顺序)检索值,并确定存储结果的内存位置(分别为左右操作数的值计算)
将结果存储在a
(作业)中。涉及a ^ b
的值计算,在报价中没有提及,但显然必须在存储之前计算结果
执行赋值表达式的值计算。这意味着放弃存储在a
中的值,准备好使用周围的表达式(值计算)。
你是对的,2和3似乎"向后"与您在纸上做事的顺序相比。但请记住,一般情况下,y
与x = y
的值不同。赋值表达式的值与x
中存储的值相同。 (示例:int x; double y = (x = 6.5);
- 然后y
是6
,而不是6.5
)。因此,我们可以将结果存储在a
中,然后提供a
作为结果。