Операторы инкремента/декремента
Операторы инкремента/декремента увеличивают или уменьшают значение объекта.
| Название оператора | Синтаксис | Можно перегрузить | Примеры прототипов (для classT) | |
|---|---|---|---|---|
| Внутри определения класса | Вне определения класса | |||
| префиксный инкремент |
++a | Да |
T& T::operator++(); |
T& operator++(T& a); |
| префиксный декремент |
--a | Да |
T& T::operator--(); |
T& operator--(T& a); |
| постфиксный инкремент |
a++ | Да |
T T::operator++(int); |
T operator++(T& a, int); |
| постфиксный декремент |
a-- | Да |
T T::operator--(int); |
T operator--(T& a, int); |
Примечания
|
||||
Префиксные операторы
Выражения префиксного инкремента и декремента имеют вид
++ выражение | ||
-- выражение |
Встроенные префиксные операторы
++x эквивалентно x += 1, за следующими исключениями:
| (до C++17) |
| (начиная с C++17) |
| (начиная с C++20) |
--x эквивалентно x -= 1, за следующими исключениями: - Если тип выражения — bool (возможно, с cv-квалификаторами), программа некорректна.
| (начиная с C++20) |
Перегрузки
При разрешении перегрузки для пользовательских операторов в разрешении перегрузки участвуют следующие сигнатуры функций для каждого арифметического типа A, который может иметь квалификатор volatile, кроме bool, а также для каждого указателя P, который может иметь квалификатор volatile и указывает на тип объекта, который может иметь cv-квалификаторы:
A& operator++(A&) | ||
bool& operator++(bool&) | (устарело)(до C++17) | |
P& operator++(P&) | ||
A& operator--(A&) | ||
P& operator--(P&) |
Постфиксные операторы
Выражения постфиксного инкремента и декремента имеют вид
выражение ++ | ||
выражение -- |
Встроенные постфиксные операторы
Результат постфиксного инкремента или декремента — значение, полученное применением преобразования lvalue в rvalue к выражению (до изменения). Тип результата — версия типа выражения без cv-квалификаторов.
Если выражение не является модифицируемым lvalue арифметического типа, отличного от bool (возможно, с cv-квалификаторами)(начиная с C++17), или указателем на полный тип объекта, программа некорректна.
| Если тип выражения имеет квалификатор volatile, инкремент или декремент считается устаревшим. | (начиная с C++20) |
++.--.Вычисление значения постфиксного инкремента или декремента упорядочено перед изменением выражения. Относительно вызова функции с неопределённым порядком следования операция постфиксного инкремента или декремента является одним вычислением.
Перегрузки
При разрешении перегрузки для пользовательских операторов в разрешении перегрузки участвуют следующие сигнатуры функций для каждого арифметического типа A, который может иметь квалификатор volatile, кроме bool, а также для каждого указателя P, который может иметь квалификатор volatile и указывает на тип объекта, который может иметь cv-квалификаторы:
A operator++(A&, int) | ||
bool operator++(bool&, int) | (устарело)(до C++17) | |
P operator++(P&, int) | ||
A operator--(A&, int) | ||
P operator--(P&, int) |
Пример
#include <iostream>
int main()
{
int n1 = 1;
int n2 = ++n1;
int n3 = ++ ++n1;
int n4 = n1++;
// int n5 = n1++ ++; // error
// int n6 = n1 + ++n1; // undefined behavior
std::cout << "n1 = " << n1 << '\n'
<< "n2 = " << n2 << '\n'
<< "n3 = " << n3 << '\n'
<< "n4 = " << n4 << '\n';
}
Вывод:
n1 = 5 n2 = 2 n3 = 4 n4 = 4
Примечания
Из-за побочных эффектов встроенные операторы инкремента и декремента следует использовать с осторожностью, чтобы избежать неопределённого поведения вследствие нарушения правил упорядочивания.
Поскольку при постфиксном инкременте и декременте создаётся временная копия объекта, в контекстах, где возвращаемое значение не используется, префиксные операторы инкремента и декремента обычно эффективнее.
Стандартная библиотека
Операторы инкремента и декремента перегружены для многих типов стандартной библиотеки. В частности, у каждого LegacyIterator перегружен operator++, а у каждого LegacyBidirectionalIterator перегружен operator--, даже если эти операторы ничего не делают для конкретного итератора.
перегрузки для арифметических типов |
|
| увеличивает или уменьшает атомарное значение на единицу (открытая функция-член std::atomic<T>) |
|
| увеличивает или уменьшает количество тактов (открытая функция-член std::chrono::duration<Rep,Period>) |
|
перегрузки для типов итераторов |
|
| продвигает итератор (открытая функция-член std::raw_storage_iterator<OutputIt,T>) |
|
продвигает или перемещает назад reverse_iterator (открытая функция-член std::reverse_iterator<Iter>) |
|
продвигает или перемещает назад move_iterator (открытая функция-член std::move_iterator<Iter>) |
|
| ничего не делает (открытая функция-член std::front_insert_iterator<Container>) |
|
| ничего не делает (открытая функция-член std::back_insert_iterator<Container>) |
|
| ничего не делает (открытая функция-член std::insert_iterator<Container>) |
|
| продвигает итератор (открытая функция-член std::istream_iterator<T,CharT,Traits,Distance>) |
|
| ничего не делает (открытая функция-член std::ostream_iterator<T,CharT,Traits>) |
|
| продвигает итератор (открытая функция-член std::istreambuf_iterator<CharT,Traits>) |
|
| ничего не делает (открытая функция-член std::ostreambuf_iterator<CharT,Traits>) |
|
| продвигает итератор к следующему совпадению (открытая функция-член std::regex_iterator<BidirIt,CharT,Traits>) |
|
| продвигает итератор к следующему подсовпадению (открытая функция-член std::regex_token_iterator<BidirIt,CharT,Traits>) |
|
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены ретроспективно к ранее опубликованным стандартам C++.
| DR | Применяется к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| CWG 2855 | C++98 | обычные арифметические преобразования применялись для встроенных префиксных инкремента и декремента, но не применялись для соответствующих постфиксных операторов[1] | также применяются |
| CWG 2901 | C++98 | преобразования lvalue в rvalue не применялись для встроенных постфиксных инкремента и декремента | применяются |
- Префиксный
++xэквивалентенx += 1, а последний применим к обычным арифметическим преобразованиям (то есть даёт общий тип для decltype(x) и int). Однако эффект постфиксногоx++— это просто «прибавление единицы кx»; бинарный оператор отсутствует, поэтому обычные арифметические преобразования не выполняются.
См. также
| Основные операторы | ||||||
|---|---|---|---|---|---|---|
| Присваивание |
Инкремент, декремент | Арифметические | Логические | Сравнения |
Доступ к членам | Другие |
a = b a += b a -= b a *= b a /= b a %= b a &= b a |= b a ^= b a <<= b a >>= b | ++a --a a++ a-- | +a -a a + b a - b a * b a / b a % b ~a a & b a | b a ^ b a << b a >> b | !a a && b a || b | a == b a != b a < b a > b a <= b a >= b a <=> b | a[...] *a &a a->b a.b a->*b a.*b | вызов функцииa(...) |
запятаяa, b |
||||||
условный операторa ? b : c |
||||||
| Специальные операторы | ||||||
|
|
||||||
| Документация по C для Операторы инкремента/декремента |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/operator_incdec