【问题标题】:Sequence point within assignment operators赋值运算符中的序列点
【发布时间】:2015-06-01 13:28:28
【问题描述】:

让我们以特定的复合赋值运算符^= 为例。 This stackoverflow page 表示在评估 ^= 之后可能尚未完成对左操作数的修改,从而使代码 a ^= b ^= a ^= b 未定义行为。但情况似乎并非如此。该标准在 5.17 [expr.ass] 中说

在所有情况下,赋值都是在值计算之后排序的 左右操作数,在计算值之前 赋值表达式。

这句话有两个关键点。 1) 主题 assignment 指的是什么?在我看来,它只是指对左操作数的修改。 2) 赋值表达式的值计算指的是什么? cppreference 说它指的是返回对 modified 对象的引用(强调我的)。

作为结论,在评估^= 之后,左操作数应该已经被修改,这与(大多数)人们的想法相矛盾。我在这里遗漏了什么吗?

【问题讨论】:

    标签: c++ assignment-operator sequence-points compound-assignment


    【解决方案1】:

    你链接到一个 C 问题。但是,这无关紧要,因为 C 和 C++ 是不同的语言。

    此外,从 C11 和 C++11 开始,序列点不再存在;而是存在关系先排序未排序不确定排序

    在那句话中:

    • 赋值表示写入a的内存位置。
    • 表达式的值计算意味着计算该表达式的值。 (例如,2 + 2 的值是4,值计算是确定4 是值的过程。

    这里有两个值计算:a ^ ba =(那个结果)。

    在引用的文本中,对于a = a ^ b,事情必须按照这个顺序发生:

    1. ab 中检索值(以任意顺序),并确定存储结果的内存位置(分别计算右操作数和左操作数的值)

      李>
    2. 将结果存储在a(赋值)中。涉及到a ^ b的值计算,引用中没有提到,但是很明显,结果必须在存储之前计算出来

    3. 执行赋值表达式的值计算。这意味着产生存储在a 中的值,以供周围的表达式使用(值计算)。

    您说得对,与您在纸上做事的顺序相比,2 和 3 似乎“倒退”了。但请记住,通常yx = y 的值不同。赋值表达式的值与 x 中存储的值相同。 (例如:int x; double y = (x = 6.5); - 那么y6,而不是6.5)。所以我们可以通过将结果存储在a 中然后提供a 作为结果来做到这一点。

    【讨论】:

    • 所以从技术上讲,与许多人的看法不同,a ^= b ^= a ^= b 实际上并不会导致未定义的行为?
    • 技术上没有sequenced after,尽管它是通俗地使用的。赋值运算符的“右操作数”是a ^ b,其值计算包括ab的值计算,然后进行异或运算得到结果。
    • @Lingxi in a ^ b ,可以按任意顺序读取ab。 (a ^= b 定义为a = a ^ b
    • @TC 是的,我就是这么说的,关于操作数(如果措辞不明确,请编辑我的帖子)
    • @Lingxi 我认为b ^= a ^= b 定义明确但a ^= b ^= a ^= b 未定义(因为它是a = a ^ (b ^= a ^= b),但是在右侧的评估中,@987654354 的两个操作数@ 未排序,一个写入a,另一个读取它)。当我有更多时间检查我是否使用了正确的术语时,我会更新我的答案。
    猜你喜欢
    • 2011-08-02
    • 2019-10-06
    • 2011-05-20
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 2015-10-02
    • 1970-01-01
    相关资源
    最近更新 更多