Почему увеличение / уменьшение цепочки префикса для встроенного типа не является UB для C ++?

В cpprefernce.com пример для приращения префикса есть такой код:

int n1 = 1;
...
int n3 = ++ ++n1;

Почему цепочечный прирост в этом случае не приводит к UB? Не нарушено ли правило для не более одного измененного в этом случае?

8

Решение

В C ++ 11 и более поздних версиях UB возникает, когда есть две записи или запись и чтение, которые не упорядочены и имеют доступ к одной и той же ячейке памяти. Но ++x эквивалентно x+=1, так ++ ++n1 эквивалентно (n1+=1)+=1и здесь чтение и запись происходят в строгой последовательности из-за свойств операторов присваивания и составного присваивания: сначала n1 читается, затем записывается один плюс исходное значение, затем читается полученное значение снова, затем записывается один плюс это значение.

В C ++ 03 это было UB, из-за старого правила, на которое вы намекаете: между двумя модификациями нет последовательности. Но в C ++ 11 больше нет точек последовательности; вместо этого есть частичный порядок «последовательность перед».

11

Другие решения

Увидеть Брайан ответить на более простые термины.

Это законно, потому что в стандарте C ++ так говорится, мой акцент … Продолжение проекта C ++ 14

5.3.2 Увеличение и уменьшение [expr.pre.incr]

Операнд префикса ++ изменяется путем добавления 1 или устанавливается в значение true, если он
is bool (это использование устарело). Операнд должен быть изменяемым
именующий. Тип операнда должен быть арифметическим типом или
указатель на полностью определенный тип объекта. Результатом является
обновленный операнд; это lvalue
, и это битовое поле, если
операнд — это битовое поле. Если x не относится к типу bool, выражение ++ x
эквивалентно х + = 1

Итак, это совершенно законно

#include <iostream>
using namespace std;

int main(){
int x =8;
int y = ++ ++ ++ ++ ++ ++ ++ ++ x;
cout << x << " " << y;

}

Выход

16 16

1.9 Выполнение программы [intro.execution]

15…Если побочный эффект на скалярном объекте не секвенирован относительно
еще один побочный эффект на тот же скалярный объект или вычисление значения
используя значение тот же скалярный объект, поведение не определено. …

И это прикрепленный пример:

void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
2

По вопросам рекламы [email protected]