Да, код действителен и не имеет неопределенного поведения. Выражения в списке инициализаторов оцениваются слева направо и упорядочиваются до вычисления конструктора 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, в котором также упоминаются аналогичные примеры, которые действуют с неопределенным поведением:
i = v[i++]; // the behavior is undefined
i = i++ + 1; // the behavior is undefined
Однако в том же абзаце сказано:
"За исключением отмеченных случаев, оценки операндов отдельных операторов и подвыражений отдельных выражений не упорядочены. [...] При вызове функции (независимо от того, функция является встроенной), каждое вычисление значения и побочный эффект, связанные с любым выражением-аргументом или с постфиксным выражением, обозначающим вызываемую функцию, упорядочены перед выполнением каждого выражения или оператора в теле вызываемой функции."
Поскольку 1) оценка выражений в списке инициализаторов выполняется слева направо, 2) выполнение конструктора S
выполняется после оценки всех выражений в списке инициализаторов и 3) присваивание i
выполняется последовательно после выполнения конструктора S
(и его оператора преобразования), поведение четко определено.
person
Andy Prowl
schedule
21.01.2013