In C++03 it is undefined behavior. In C++11 it is not. There is no sequence point between the various pre-increments. If i
was a user-defined type, it would be well-defined behavior because then there would be a function call (a sequence point).
In C++11, the idea of sequence points was replaced with sequenced before/sequenced after. Defect 637 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637) provides an example of a previously undefined construct becoming well-defined (i = ++i + 1
).
To understand why it's not undefined behavior, let's look at the pieces we need. ++i
is equivalent to i = i + 1
(except i
is evaluated only once). Further if we substitute i = i + 1
with inc
, ++(i = i + 1)
becomes inc = inc + 1
.
[expr.ass] states:
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.
Thus the assignment in i = i + 1
is sequenced before value computation of inc
; however, the assignment in inc = inc + 1
is sequenced after value computation of inc
. There is no undefined behavior because the assignments are sequenced.