i += ++i 在 C++0x 中是未定义的行为吗?
Posted
技术标签:
【中文标题】i += ++i 在 C++0x 中是未定义的行为吗?【英文标题】:Is i += ++i undefined behavior in C++0x? 【发布时间】:2011-04-25 08:11:12 【问题描述】:我非常相信我发现的解释是 i = ++i
is not undefined 就 C++0x 而言,但我无法判断 i += ++i
的行为是否明确定义或不是。有接盘侠吗?
【问题讨论】:
g++ 说是的,它是 UB。 @KennyTM :我有 4.5.0 版,它警告我即使 i = ++i 未定义。你用的是什么版本?您是否成功编译 i = ++i 而没有警告? i = ++i 和 i += ++i 都是 UB @Armen : i = ++i 在 C++0x 中定义良好。 @Armen :您可能想阅读open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637 【参考方案1】:使i = ++i
定义良好的推理同样可以用来证明i += ++i
也必须是良好定义的。
i += ++i
等价于i += (i += 1)
,并且新的排序规则要求赋值发生在i += 1
子表达式的值计算之前。
这意味着表达式i += ++i
的结果必须与i = 2 * i + 1
的结果相同。
编辑:我必须修改我的答案,因为行为毕竟是未定义的。i += ++i
的行为是未定义的,因为子表达式 i
(左侧参数)和 ++i
的值计算相对于彼此是无序的,其中一个包含对象的更新i
.
这对于表达式i = ++i
来说不是问题,因为左侧的i
没有经历左值到右值的转换,这在i += ++i
的情况下会发生。
附带说明:不要在任何严肃的项目中编写此类代码。它过于依赖准确地了解排序规则,并且会有很多人要么没有正确理解排序规则,不知道 DR 637 导致的规则变化,要么因为错过了一些重要的事情而被绊倒有问题的表达式的各个方面(就像我在撰写此答案的第一个修订版时发生的那样)。
【讨论】:
i += ++i 将等价于 i = i + ++i;这样 i 只被评估一次。但是,是否定义了首先评估 i 或 ++i 中的哪一个? @Saurabh:你是对的。i = ++i
和i += ++i
之间的区别在于左侧i
的值计算,它与++i
无序。这使得结果未定义。我会相应地更新我的答案。
@Bart 我想知道“在所有情况下,作业都是按顺序排列的……”究竟是什么意思。 “任务”究竟是什么?复合赋值是赋值。我们可以说复合赋值由prvalue评估和副作用组成吗?
不过,我同意你的解释。但我不会打赌。另外,我希望措辞能更清楚一点。 “E1 op = E2 形式的表达式的行为等价于 E1 = E1 op E2,只是 E1 只计算一次。”
@Johannes:“只评估一次”意味着必须同时有效地进行泛右值和纯右值求值,或者纯右值求值必须使用泛值值求值的结果。如果 E1 包含副作用(例如,当它是函数调用时),那么副作用可能只发生一次。以上是关于i += ++i 在 C++0x 中是未定义的行为吗?的主要内容,如果未能解决你的问题,请参考以下文章