TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #495 5.86K
​​Различаем преинкремент и постинкремент
#новичкам

Новичкам всегда не просто даются перегрузки операторов. Не то, чтобы кому-то часто приходится перегружать операторы. Но уж эти *нкременты точно редко. Из-за этого особенности постоянно забываются. Давайте же во всем разберемся.

Есть операторы инкремента и декремента. Первые увеличивают значение на какую-то условную единицк, вторые - уменьшаю. Они подразделяются на 2 формы: пре- и пост-. Далее будем все разбирать на примере операторов инкремента, для декремента все аналогично, только меняете плюс на минус.

Преинкремент - увеличивает значение на единицу и возвращает ссылку на уже увеличенное значение. Синтаксис использования такой: ++value.

Постинкремент - делает копию исходного числа, увеличивает на единицу оригинал, и возвращает копию по значению. Синтаксис использования такой: value++.

Обычно внешний вид перегрузки операторов внутри описания класса такой:

возвращаемое_значение operator{символы_вызова_оператора}(аргументы).

Например, оператор копирования вызывается с помощью оператора присваивания(=). Поэтому подставляем в шаблон на место возвращаемое_значение ссылку на объект, на место символы_вызова_оператора подставляем =, на место аргументов - const Type&. Получается так:

Type& operator=(const Type&);


Но теперь возникает вопрос. С++ не различает функции, у которых то же имя, то же те же аргументы, но разные возвращаемые значения. У нас как раз такая ситуация: названия одинаковые(operator++), возвращаемые значения разные(в одном случае возвращаем по ссылке, во втором - по значению) и одинаково отсутствуют аргументы. Если бы мы определили операторы так:

Type& operator++() {
value_ += 1;
return *this;
}

Type operator++() {
auto tmp_value = *this;
value_ += 1;
return tmp_value;
}


То была бы примерно такая ошибка компиляции: functions that differ only in their return type cannot be overloaded.

Что же делать?

Примерно таким же вопросом задался Страуструп и сделал ход конем(правда конь ходил на костылях). Он связал префиксный оператор с человеческой формой объявления, а постфиксный - с вот такой:

Type operator++(int) {
auto tmp_value = *this;
value_ += 1;
return tmp_value;
}


Он ввел безымянный интовый параметр функции. Теперь чисто технически, компилятор сможет различить 2 вызова этих операторов и правильно заметчить эти вызовы на нужные определения.

Если видит префикс - выбирает оператор без аргумента, видит постфикс - выбирает с аргументом.

Вопрос, почему тип аргумента именно int - остается открытым. Наверное так было проще.

Итого, так перегружаются операторы инкремента:

struct Type {
Type& operator++() {
value_ += 1;
return *this;
}

Type operator++(int) {
auto tmp_value = *this;
value_ += 1;
return tmp_value;
}
private:
IntegerLikeType value_;
};


Think of your decisions twice. Stay cool.

#cppcore
  • 🔥 37
  • 👍 19
  • ❤ 7
  • 😁 5
  • 👎 2
  • ❤‍🔥 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →