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


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

9 60

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

или

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

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

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

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

легко подумать, что выражение ++x поэтому эквивалентно assignmnet (x=x+1). Это не совсем так, однако, потому что инкремент - это операция, которая может означать разные вещи в разных контекстах. В случае простого примитивного целого числа, действительно ++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

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

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

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

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

ограничения

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

семантика

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

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

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

ограничения

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

семантика

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

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

предварительный шаг, прежде чем инкрементировать значение ++ например:

(++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++ ;

печатает 9 2 !! Это потому, что приведенное выше выражение эквивалентно:

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