Native operator expressions and overloaded operator expressions are not equivalent. When values are bound to function arguments, there is a sequence point which makes the
operator++()
versions well-defined. However, this does not exist for the native-type case.
In all four cases, the variable
i
changes twice within the full-expression. Since there are no
,
,
||
, or
&&
operators in the expressions, this results in undefined behavior (UB).
According to §5/4 of the C++ standard: "Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression."
For C++0x, §1.9/15 states: "The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined."
Value computations and side effects are distinct. If
++i
is equal to
i = i+1
, then
+
is the value computation and
=
is the side effect. As per 1.9/12, "evaluation of an expression (or a sub-expression) in general includes both value computations ... and initiation of side effects." Therefore, although value computations are more strongly sequenced in C++0x than in C++03, two side effects in the same expression, unless otherwise sequenced, produce UB.
§5.17/1 defining the assignment operators says, "In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression." Also, §5.3.2/1 on the preincrement operator says: "If x is not of type bool, the expression ++x is equivalent to x+=1 [Note: see … addition (5.7) and assignment operators (5.17) …]."
Hence
++ ++ x
is shorthand for
(x += 1) += 1
, and this is well-defined for steps 1 and 3, but undefined for steps 2 and 4.
The glvalue (address) of a named object is constant and cannot have dependencies, so in
i == ++i;
, the glvalue of
i
is not intended to be included as an ambiguous dependency by 1.9/15.
( i % 2? i : j ) = ++ i; // certainly undefined
这里,赋值运算符左侧的glvalue取决于对prvalue i 的副作用。 i
的地址并不成问题;而是会受到?:
表达式的影响。
也许一个好的反例是
int i = 3, &j = i;
j = ++ i;
这里的j
具有与i
不同但相同的glvalue。这是明确定义的,但是i = ++i
却没有定义。这代表了编译器可以应用于任何情况的微不足道的转换。
1.9/15 应该说:
如果标量对象上的副作用在与同一标量对象的另一个副作用或使用同一标量对象的prvalue进行值计算时无序关联,则行为未定义。
:)
- Prasoon Saurav++
[inner] 和++
[outer] 相关的副作用在彼此之间没有排序(尽管值计算是有序的)。:)
- Prasoon Saurav