Постинкрементная и прединкрементная концепция? - PullRequest
64 голосов
/ 15 декабря 2010

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

Ответы [ 11 ]

104 голосов
/ 15 декабря 2010

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

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

Зв

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

++x

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

x++

увеличивает x и выдает (как результат выражения) исходное значение x.

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

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

26 голосов
/ 15 декабря 2010
int i, x;

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

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

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

17 голосов
/ 18 декабря 2013

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

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

Следующее неверно!


x = y ++

X равно y post increment. Логично предположить, что X равно значению Y после операция увеличения. Пост , означающий после .

или

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


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

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

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

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

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

14 голосов
/ 15 декабря 2010

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

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

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

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

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

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

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

6 голосов
/ 15 декабря 2010

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

x++;
++x;

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

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

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

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

4 голосов
/ 15 декабря 2010
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.

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

1 голос
/ 27 апреля 2019

Пост приращения (a ++)

Если int b = a ++, тогда это означает

int b = a;

a = a+1;

Здесь мы добавляем 1 к значению. Значение возвращается до того, как сделано приращение,

Например, а = 1; b = a ++;

Тогда b = 1 и a = 2

Предварительное увеличение (++ a)

Если int b = ++ a; тогда это означает

a=a+1;

int b=a ;

Предварительное увеличение: это добавит 1 к основному значению. Значение будет возвращено после увеличения, для a = 1; b = ++ a; Тогда b = 2 и a = 2.

0 голосов
/ 14 февраля 2019

Поскольку у нас теперь есть встроенные фрагменты JavaScript, я мог бы также добавить интерактивный пример увеличения до и после. Это не C ++, но концепция остается прежней.

let A = 1;
let B = 1;

console.log('A++ === 2', A++ === 2);
console.log('++B === 2', ++B === 2);
0 голосов
/ 14 октября 2014

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

(++v) or 1 + v

Пост-инкремент после увеличения значения ++ например ::1006*

(rmv++) or rmv + 1

Программа:

int rmv = 10, vivek = 10;
cout << "rmv++ = " << rmv++ << endl; // the value is 10
cout << "++vivek = " << ++vivek; // the value is 11
0 голосов
/ 29 мая 2013

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