本机运算符表达式不等同于重载运算符表达式。在值与函数参数的绑定处有一个序列点,这使得operator++()
版本定义明确。但对于本机类型的情况而言,这种情况不存在。
在所有四种情况下,i
在完整表达式中改变两次。既然没有,
, ||
, or &&
出现在表情里,那就是即时UB。
§5/4:
在上一个和下一个序列点之间,标量对象的存储值最多应通过表达式的求值修改一次。
编辑 C++0x(已更新)
§1.9/15:
运算符操作数的值计算在运算符结果的值计算之前排序。如果标量对象上的副作用相对于同一标量对象上的另一个副作用或使用同一标量对象的值的值计算是无序的,则该行为是未定义的。
但请注意,值计算和副作用是两个不同的东西。如果++i
相当于i = i+1
, then +
是值计算和=
是副作用。从 1.9/12 开始:
表达式(或子表达式)的求值通常包括值计算(包括确定用于左值求值的对象的身份以及获取先前分配给对象用于纯右值求值的值)和副作用的启动。
So although the value computations are more strongly sequenced in C++0x than C++03, the side effects are not. Two side effects in the same expression, unless otherwise sequenced, produce UB.
Value computations are ordered by their data dependencies anyway and, side effects absent, their order of evaluation is unobservable, so I'm not sure why C++0x goes to the trouble of saying anything, but that just means I need to read more of the papers by Boehm and friends wrote.
Edit #3:
感谢 Johannes 解决了我在 PDF 阅读器搜索栏中输入“sequenced”的懒惰问题。无论如何,我要去睡觉并起床进行最后两个编辑……对;v) 。
§5.17/1 定义赋值运算符说
在所有情况下,赋值都在右操作数和左操作数的值计算之后、赋值表达式的值计算之前排序。
关于预自增运算符的§5.3.2/1 还说
如果 x 不是 bool 类型,则表达式 ++x 等价于 x+=1 [注:参见…加法 (5.7) 和赋值运算符 (5.17)…]。
凭借这个身份,++ ++ x
是简写(x +=1) +=1
。那么,让我们解释一下。
- 评估
1
在远处的 RHS 上并下降到括号中。
- 评价内在
1
以及值(prvalue)和地址(glvalue)x
.
- Now we need the value of the += subexpression.
- 我们已经完成了该子表达式的值计算。
- 在赋值可用之前,必须对赋值副作用进行排序!
- 将新值分配给
x
,与子表达式的左值和纯右值结果相同。
- 我们现在已经走出困境了。整个表达式现在已简化为
x +=1
.
So, then