4

§5.2.6/1我们有(重点是我的):

后缀 ++ 表达式的值是其操作数的值。[注意:获得的值是原始值的副本-结束注释]操作数应为可修改的左值。操作数的类型应为除 cv bool 以外的算术类型,或指向完整对象类型的指针。操作数对象的值通过加 1 来修改。++表达式的值计算在操作数对象修改之前排序. 对于不确定顺序的函数调用,后缀 ++ 的操作是单次求值。[ 注意:因此,函数调用不应干预左值到右值的转换以及与任何单个后缀 ++ 运算符相关的副作用。— 尾注] 结果是纯右值。结果的类型是操作数类型的 cv 非限定版本。如果操作数是不能表示递增值的位域,则位域的结果值是实现定义的。另见 [expr.add] 和 [expr.ass]。

也就是说,操作数对象的修改是在表达式的值计算之后排序++的。

§5.18/1我们有(重点是我的):

赋值运算符 (=) 和复合赋值运算符都从右到左分组。所有这些都需要一个可修改的左值作为它们的左操作数,并返回一个指向左操作数的左值。如果左操作数是位域,则所有情况下的结果都是位域。在所有情况下,赋值都在左右操作数的值计算之后和赋值表达式的值计算之前进行排序。对于不确定顺序的函数调用,复合赋值的操作是单次求值。[注意:因此,函数调用不应干预左值到右值的转换以及与任何单个复合赋值运算符相关的副作用。——尾注]

赋值表达式
      条件表达式
      逻辑或表达式 赋值运算符 初始化子句
      抛出表达式

赋值运算符
      = *= /= %= += -= >>= <<= &= ^= |=之一

在赋值运算符的左右操作数的值计算之后,赋值也是排序的。

因此,如果我们考虑表达式

i = i++;

我们从 §5.2.6/1 知道表达式的副作用i++,在这个赋值表达式的 RHS 上是在 的值计算之后排序的i++。并且从 §5.18/1 中我们知道,赋值运算符对 LHS 的赋值对应的副作用i是在赋值运算符的左右操作数的值计算之后排序的。

但是我如何证明这两个副作用是未排序的,以证明表达式i = i++;显示未定义的行为?

4

1 回答 1

8

首先,如果 A 没有在 B 之前排序并且 B 没有在 A 之前排序,那么 A 和 B 是未排序的( 1.9/13)。这就是无序的定义。其次,如果标量对象上的两个副作用未排序,则行为未定义 (1.9/15)。因此,除非您能找到说明后增量和赋值是按顺序排列的(而您不会),否则行为是未定义的。

于 2016-02-01T18:33:57.630 回答