从§5.2.6/1开始,我们有(重点是我的(:
后缀 ++ 表达式的值是其操作数的值。[ 注:获得的值是原始值的副本 — 尾注 ] 操作数应为可修改的右值。操作数的类型 应是 cv bool 以外的算术类型,或指向 完整的对象类型。操作数对象的值由 加 1。++ 表达式的值计算为 在修改操作数对象之前排序。跟 对于不确定顺序的函数调用,操作 的后缀++是一个单一的评估。[ 注意:因此,函数 呼叫不得干预左值到右值转换和 与任何单个后缀 ++ 运算符关联的副作用。 — 完 注意 ] 结果是一个 prvalue。结果的类型为 操作数类型的 CV 非限定版本。如果操作数是 不能表示递增值的位字段,即结果 位字段的值由实现定义。参见 [expr.add] 和[expr.ass]。
也就是说,操作数对象的修改是在++
表达式的值计算之后排序的。
从§5.18/1开始,我们有(重点是我的(:
赋值赋值运算符 (=( 和复合赋值运算符全部 从右到左分组。都需要一个可修改的左值作为他们的左边 操作数并返回一个引用左操作数的左值。结果 在所有情况下,如果左操作数是位字段,则为位字段。一起 在这种情况下,赋值在 左右操作数,以及 赋值表达式。关于不确定序列 函数调用,复合赋值的操作是单个 评估。[ 注意:因此,函数调用不应干预 在左值到重值转换和相关副作用之间 使用任何单个复合赋值运算符。 — 尾注 ]
赋值表达式:
条件表达式
逻辑或表达式赋值运算符初始值设定项子句
抛出表达式赋值运算符:以下之一
= *=/= %= += -=>>= <<= &= ^= |=
也在赋值运算符的左右操作数的值计算之后排序。
因此,如果我们考虑表达式
i = i++;
我们从 §5.2.6/1 中知道表达式的副作用 i++
,对这个赋值表达式的 RHS 的副作用是在 i++
的值计算之后排序的。从 §5.18/1 我们知道,赋值运算符的 LHS 上与i
赋值相对应的副作用是在赋值算子的左右操作数的值计算之后排序的。
但是,我如何证明这两个副作用是未排序的,以证明表达式i = i++;
显示未定义的行为?
A 之前排序,则 A 和 B 未排序 (1.9/13(。这就是无序的定义。其次,如果标量对象的两个副作用未排序,则行为未定义 (1.9/15(。因此,除非你能找到一些东西说后增量和赋值是有序的(你不会(,否则行为是不确定的。