Bel*_*loc 4 c++ partial-ordering language-lawyer c++17
从§5.2.6/ 1我们得到(重点是我的):
后缀++表达式的值是其操作数的值.[注意:获得的值是原始值的副本 - 结束注释]操作数应是可修改的左值.操作数的类型应该是cv bool以外的算术类型,或者是指向完整对象类型的指针.通过向其添加1来修改操作数对象的值.在修改操作数对象之前,对++表达式的值计算进行排序.对于不确定顺序的函数调用,后缀++的操作是单个评估.[注意:因此,函数调用不应介入左值到右值的转换和与任何单个后缀++运算符相关的副作用. - 结束注释]结果是一个prvalue.结果的类型是操作数类型的cv-nonqualified版本.如果操作数是不能表示递增值的位字段,则位字段的结果值是实现定义的.另请参见[expr.add]和[expr.ass].
也就是说,在表达式的值计算之后对操作数对象的修改进行排序++.
从§5.18/ 1我们得到(重点是我的):
赋值运算符(=)和复合赋值运算符都是从右到左分组.所有都需要一个可修改的左值作为左操作数,并返回一个左值操作数的左值.如果左操作数是位字段,则所有情况下的结果都是位字段.在所有情况下,在右和左操作数的值计算之后,以及在赋值表达式的值计算之前,对赋值进行排序.对于不确定序列的函数调用,复合赋值的操作是单个评估.[注意:因此,函数调用不应介入左值到右值的转换和与任何单个复合赋值运算符相关的副作用. - 结束说明]
assignment-expression:
conditional-expression
logical-or-expression assignment-operator initializer-clause
throw-expressionassignment-operator:其中一个
=*=/=%= + = - = >> = << =&= ^ = | =
在赋值运算符的右和左操作数的值计算之后,也对赋值进行排序.
因此,如果我们考虑表达式
i = i++;
Run Code Online (Sandbox Code Playgroud)
我们从§5.2.6/ 1中知道,表达式i++对该赋值表达式的RHS的副作用是在计算值之后对其进行排序i++.从§5.18/ 1我们知道,在i赋值运算符的右和左操作数的值计算之后,对应于赋值运算符的LHS的赋值的副作用被排序.
但是,为了证明表达式i = i++;显示未定义的行为,我如何证明这两个副作用是无效的?
首先,如果A不B之前测序,B不是A之前测序,则A和B是未测序(1.9/13).这是未经测序的定义.其次,如果对标量对象的两个副作用未被排序,则行为未定义(1.9/15).因此,除非你能找到一些说明后增量和赋值顺序(并且你不会)的东西,否则行为是未定义的.