Ответ 1
Да, код действителен и не имеет поведения undefined. Выражения в списке инициализаторов оцениваются слева направо и упорядочиваются перед оценкой конструктора S
. Поэтому ваша программа должна последовательно присваивать значение 2
переменной i
.
Цитата из § 8.5.4 стандарта С++:
"В списке инициализаторов списка с привязкой к инициализации предложения инициализатора, включая все, что является результатом разложений пакетов (14.5.3), оцениваются в том порядке, в котором они отображаются. То есть, каждое вычисление значения и побочный эффект, связанное с заданным предложением инициализатора , секвенируется до с каждым вычислением значения и побочным эффектом, связанным с любое предложение инициализатора, которое следует за ним в разделенном запятыми списке списка инициализаторов."
Таким образом, происходит следующее:
-
++i
получает оценку, даваяi = 1
(первый аргумент конструктораS
); -
++i
получает оценку, даваяi = 2
(второй аргумент конструктораS
); Выполняется конструктор -
S
; -
S
выполняется оператор преобразования, возвращающее значение2
; - Значение
2
присваиваетсяi
(уже имеющему значение2
).
Другим важным пунктом Стандарта является § 1.9/15, в котором также упоминаются аналогичные примеры, которые имеют поведение undefined:
i = v[i++]; // the behavior is undefined
i = i++ + 1; // the behavior is undefined
Однако в том же абзаце говорится:
"За исключением тех случаев, когда отмечено, оценки операндов отдельных операторов и подвыражений отдельных выражений не имеют никакого значения. [...] При вызове функции (независимо от того, функция является встроенной), каждое вычисление значения и побочный эффект, связанный с любым выражением аргумента, или с выражением postfix, обозначающим вызываемую функцию, секвенируются перед выполнением каждого выражения или оператора в теле вызываемой функции."
Поскольку 1) оценка выражений в списке инициализаторов секвенирована слева направо, 2) выполнение конструктора S
секвенируется после оценки всех выражений в списке инициализаторов и 3) присваивание i
секвенируется после выполнения конструктора S
(и его оператора преобразования), поведение корректно определено.