Подтвердить что ты не робот

Undefined поведение при повторном использовании оператора prefix ++

Я прочитал этот ответ о поведении undefined, где увидел следующий оператор:

++++++i;     // UB, parsed as (++(++(++i)))

Я не думаю, что это поведение undefined. У меня есть сомнения, действительно ли это UB на С++? Если да, то как?

Кроме того, я сделал программу и скомпилировал ее с помощью команды g++ prog.cpp -Wall -Wextra -std=gnu++1z -pedantic, она отлично работает без предупреждения. Он дает ожидаемый результат.

#include <iostream>
using namespace std;

int main()
{
    int i = 0;
    cout<<++++++i<<endl;
}
4b9b3361

Ответ 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, потому что назначения упорядочены.

Ответ 2

Иногда поведение undefined, хотя трудно представить, как это может быть неправильно. Но pre-С++ 11, это был undefined, потому что один и тот же объект несколько раз изменялся без указания промежуточной последовательности.

Можно представить себе компилятор, который "оптимизировал" код, объединив все изменения в i. Таким образом, каждый шаг увеличивается с увеличением исходного значения. Но это не главное. UB - UB, если стандарт говорит об этом. Не имеет значения, можем ли мы представить, как это может потерпеть неудачу.