Постфиксный и префиксный инкремент понятие?

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

9 ответов


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

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

так.

для встроенного оператора префикса 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 в должности инкремент. Что логически означает, что X равно значению Y после инкремент операция завершена. в должности смысл после.

или

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


Как это работает на самом деле наоборот. Это понятие сбивает с толку, потому что язык вводит в заблуждение. В этом случае мы нельзя использовать слова для определения поведения.
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++. Вы можете видеть, что оператор postfix действительно действует на свой операнд, но он возвращает старое значение до приращения, поэтому результат выражения x++ значение до инкремента. x, однако, is увеличивается.

в префикс increment также увеличивает свой операнд, но он дает значение операнда после инкремент:

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

это означает, что выражение ++x принимает значение x после инкремент.

легко подумать, что выражение ++x поэтому эквивалентно assignmnet (x=x+1). Однако это не совсем так, потому что an инкремент - это операция, которая может означать разные вещи в разных контекстах. В случае простого примитивного целого числа, действительно ++x - это взаимозаменяемый для (x=x+1). Но в случае типа класса, такого как итератор связанного списка, префиксное приращение итератора определенно не означает "добавление одного к объекту".


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

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

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

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


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

6.5.2.4 постфиксные операторы инкремента и декремента

ограничения

1 операнд постфиксного приращения или оператор декремента должны иметь квалифицированный или неквалифицированный real или типа указатель и должен быть модифицируемым именующее выражение.

семантика

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

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

6.5.3.1 операторы инкремента и декремента префикса

ограничения

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

семантика

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

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


pre инкремент перед значением инкремента ++ например:

(++v) or 1 + v

пост инкремент после инкремента значение ++ например:

(rmv++) or rmv + 1

программа:

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

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

дано

  int a=1;

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

 a++ + a++ + a++

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

этот пример еще более запутанной:

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

печатает 92 !! Это связано с тем, что приведенное выше выражение эквивалентно:

operator<<( 
  operator<<( 
    operator<<( cout, a++ + a++ ), 
    "<->"
  ), 
  a++ + a++ + a++ 
)