Является ли * & ++ я причиной поведения 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.