Ответ 1
В С++ 03 это поведение undefined. В С++ 11 это не так. Между различными предварительными приращениями нет точки последовательности. Если i
был пользовательским типом, это было бы корректно, потому что тогда был бы вызов функции (точка последовательности).
В С++ 11 идея точек последовательности была заменена секвенированной до/секвенированной после. Дефект 637 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637) служит примером более ранней конструкции undefined (i = ++i + 1
).
Чтобы понять, почему это не поведение undefined, давайте посмотрим на нужные нам фрагменты. ++i
эквивалентен i = i + 1
(кроме i
оценивается только один раз). Далее, если подставить i = i + 1
к inc
, ++(i = i + 1)
станет inc = inc + 1
.
[expr.ass] указывает:
Во всех случаях назначение выполняется после вычисления значения правого и левого операндов и перед вычислением значения выражения присваивания.
Таким образом, назначение в i = i + 1
секвенировано перед вычислением значения inc
; однако назначение в inc = inc + 1
является секвенированным вычислением значения после inc
. Существует не поведение undefined, потому что назначения упорядочены.