Пост-инкремент и концепция предварительного инкремента?

Я не понимаю концепцию постфикса и приращения приращения или уменьшения. Может ли кто-нибудь дать лучшее объяснение?

Все четыре ответа до сих пор неверны , поскольку они утверждают определенный порядок событий.

Полагая, что «городская легенда» привела многих новичков (и профессионалов) в заблуждение, а именно бесконечный stream вопросов о Неопределенном Поведении в выражениях.

Так.

Для встроенного оператора префикса C ++,

++x 

приращения x и выражают результат выражения x как lvalue, тогда как

 x++ 

приращения x и выдает в качестве выражения исходное значение x .

В частности, для x++ нет никакого временного упорядочения, подразумеваемого для приращения и создания исходного значения x . Компилятор может свободно испускать машинный код, который создает исходное значение x , например, он может присутствовать в каком-либо регистре, и это задерживает приращение до конца выражения (следующая точка последовательности).

Люди, которые неверно полагают, что приращение должно на первом месте, и их много, часто заключают, что определенные выражения должны иметь четко определенный эффект, когда у них действительно есть неопределенное поведение.

 int i, x; i = 2; x = ++i; // now i = 3, x = 3 i = 2; x = i++; // now i = 3, x = 2 

«Post» означает «после» – то есть, приращение выполняется после считывания переменной. «Pre» означает раньше – поэтому значение переменной сначала увеличивается, а затем используется в выражении.

Никто не ответил на вопрос: почему это понятие запутывает?

В качестве основного специалиста в области компьютерных наук мне потребовалось некоторое время, чтобы понять это из-за того, как я читаю код.

Неверное!


x = y ++

X равно приращению y post . Что логически показалось бы, что X равно значению Y после выполнения операции увеличения. Значение после .

или

x = ++ y
X равно y pre -increment. Что логически показалось бы, что X равно значению Y до того, как операция инкремента будет выполнена. Предварительное значение раньше .


То, как это работает, на самом деле противоположное. Эта концепция запутанна, потому что язык вводит в заблуждение. В этом случае мы не можем использовать слова для определения поведения.
x = ++ y фактически считывается, поскольку X равно значению Y после приращения.
x = y ++ фактически считается, поскольку X равно значению Y перед приращением.

Слова pre и post являются обратными в отношении семантики английского языка . Они означают только то, где ++ есть отношение Y. Ничего больше.

Лично, если бы у меня был выбор, я бы переключил значения ++ y и y ++. Это всего лишь пример идиомы, которую я должен был изучить.

Если есть метод этого безумия, я хотел бы знать простым языком.

Спасибо за прочтение.

Разница между приращением постфикса , x++ и приращением префикса , ++x , заключается именно в том, как два оператора оценивают свои операнды. Постерическое приращение концептуально копирует операнд в память, увеличивает исходный операнд и, наконец, дает значение копии. Я думаю, это лучше всего иллюстрируется реализацией оператора в коде:

 int operator ++ (int& n) // postfix increment { int tmp = n; n = n + 1; return tmp; } 

Вышеприведенный код не будет компилироваться, потому что вы не можете переопределить операторы для примитивных типов. Компилятор также не может сказать здесь, что мы определяем постфиксный оператор, а не префикс , но давайте притворимся, что это правильный и действительный C ++. Вы можете видеть, что постфиксный оператор действительно действует на свой операнд, но он возвращает старое значение до приращения, поэтому результатом выражения x++ является значение до приращения. x , тем не менее, увеличивается.

Приращение префикса также увеличивает его операнд, но он дает значение операнда после приращения:

 int& operator ++ (int& n) { n = n + 1; return n; } 

Это означает, что выражение ++x оценивает значение x после приращения.

Легко думать, что выражение ++x поэтому эквивалентно присваиванию сети (x=x+1) . Однако это не так, потому что приращение – это операция, которая может означать разные вещи в разных контекстах. В случае простого примитивного целого, действительно, ++x заменяется на (x=x+1) . Но в случае типа classа, такого как iterator связанного списка, приращение приставки iteratorа наиболее определенно не означает «добавление одного к объекту».

Это довольно просто. Оба будут увеличивать значение переменной. Следующие две строки равны:

 x++; ++x; 

Разница заключается в том, что вы используете значение переменной, которая увеличивается:

 x = y++; x = ++y; 

Здесь обе линии увеличивают значение y на единицу. Однако первый присваивает значение y до приращения к x, а второе присваивает значение y после приращения к x.

Таким образом, существует только разница, когда приращение также используется как выражение. Приращения после инкремента после возврата значения. Предварительное приращение увеличивается до.

 int i = 1; int j = 1; int k = i++; // post increment int l = ++j; // pre increment std::cout << k; // prints 1 std::cout << l; // prints 2 

Приращение вставки означает, что значение i увеличивается после того, как оно было присвоено k . Тем не менее, pre increment подразумевает, что значение j увеличивается до того, как оно будет присвоено l .

То же самое относится к декременту.

Из стандарта C99 (C ++ должен быть тем же самым, если запретить странную перегрузку)

6.5.2.4 Операторы приращения и декремента Postfix

Ограничения

1 Операнд оператора приращения или уменьшения постфикса должен иметь квалифицированный или неквалифицированный реальный или указательный тип и должен быть изменяемым значением lvalue.

Семантика

2 Результатом оператора postfix ++ является значение операнда. После того, как результат будет получен, значение операнда будет увеличено. (То есть к нему добавляется значение 1 соответствующего типа.) См. Обсуждения аддитивных операторов и составное назначение для информации о ограничениях, типах и преобразованиях и эффектах операций над указателями. Побочный эффект обновления сохраненного значения операнда должен происходить между предыдущей и следующей точкой последовательности.

3 Оператор постфикса аналогичен оператору postfix ++, за исключением того, что значение операнда уменьшается (т. Е. Из него вычитается значение 1 соответствующего типа).

6.5.3.1 Операторы приращения и уменьшения префиксов

Ограничения

1 Операнд оператора приращения или уменьшения префикса должен иметь квалифицированный или неквалифицированный реальный или указательный тип и должен быть изменяемым значением lvalue.

Семантика

2 Значение операнда оператора prefix ++ увеличивается. Результатом является новое значение операнда после инкремента. Выражение ++ E эквивалентно (E + = 1). См. Обсуждения аддитивных операторов и составное назначение для информации о ограничениях, типах, побочных эффектах и ​​преобразованиях и эффектах операций над указателями.

3 Оператор префикса аналогичен оператору префикса ++, за исключением того, что значение операнда уменьшается.

Предварительное приращение до значения increment ++ например:

 (++v) or 1 + v 

Приращение post после инкремента значения ++ eg:

 (rmv++) or rmv + 1 

Программа:

 int rmv = 10, vivek = 10; cout << "rmv++ = " << rmv++ << endl; // the value is 10 cout << "++vivek = " << ++vivek; // the value is 11 

Вы также должны знать, что поведение операторов postincrement / decment отличается в C / C ++ и Java.

Данный

  int a=1; 

в C / C ++ выражение

  a++ + a++ + a++ 

оценивается до 3, а в Java – до 6. Угадайте, почему …

Этот пример еще более запутанным:

 cout << a++ + a++ + a++ << "<->" << a++ + a++ ; 

отпечатки 9 <-> 2 !! Это связано с тем, что вышеупомянутое выражение эквивалентно:

 operator<<( operator<<( operator<<( cout, a++ + a++ ), "<->" ), a++ + a++ + a++ ) 
Давайте будем гением компьютера.