Является ли * & ++ я причиной поведения undefined в С++ 03?

В еще один ответ было указано, что до С++ 11, где i является int, тогда используйте выражение:

*&++i

вызвало поведение undefined. Это правда?

По другому ответу было небольшое обсуждение в комментариях, но это кажется неубедительным.

Ответ 1

Не имеет смысла спрашивать, имеет ли *&++i UB. Отсрочка не обязательно получает доступ к сохраненному значению (ранее или новому) i, как вы можете видеть, используя это как выражение инициализатора для ссылки. Только если участвует преобразование rvalue (использование в таком контексте), есть ли вообще вопрос для обсуждения. И тогда, поскольку мы можем использовать значение ++i, мы можем использовать значение *&++i с точно такими же предостережениями, как и для ++i.

Первоначальный вопрос касался в основном i = ++i, что совпадает с i = *&++i. Это было поведение undefined в С++ 03, из-за того, что i изменялось дважды между точками последовательности и хорошо определено в С++ 11 из-за побочных эффектов оператора присваивания, секвенированных после значения вычисления левой и правой сторон.

Возможно, важно отметить, что ненормативные примеры в стандартах С++ 98 и С++ 03 были неправильными, описывая некоторые случаи формального undefined Поведения как просто неопределенного поведения. Таким образом, намерение не было полностью ясным, на всем пути назад. Хорошее эмпирическое правило состоит в том, чтобы просто не полагаться на такие неясные угловые случаи языка, чтобы избежать их: не нужно быть адвокатом языка, чтобы иметь смысл кода & hellip;

Ответ 2

Я думаю, что вопрос имеет смысл только в том случае, если мы имеем дело с выражением:

i = *&++i;

Соответствующая цитата в стандарте С++ 03 будет [expr]/4:

За исключением тех случаев, когда отмечено, порядок оценки операндов отдельных операторов и подвыражений отдельных выражения и порядок, в которых происходят побочные эффекты, не определены. Между предыдущими и следующая точка последовательности скалярный объект должен иметь свое сохраненное значение, измененное не более чем один раз оценкой выражения. Кроме того, к предыдущему значению следует обращаться только для определения значения, которое необходимо сохранить. Требования настоящего параграфа выполняются для каждого допустимого упорядочения подвыражений полного выражение; в противном случае поведение undefined.

i = ++i + 1; // the behavior is unspecified

Мы можем просто сравнить последовательность i = *&++i vs i = ++i + 1, чтобы определить, что одно и то же правило заставляет обе быть неуказанными. Это оба выражения вида:

i = f(++i);

Для любой функции f показание i в левой части и побочный эффект ++i в правой части не секвенированы относительно друг друга. Следовательно, поведение undefined.