Namespaces
Variants

Increment/decrement operators

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Операторы инкремента/декремента увеличивают или уменьшают значение объекта.

Название оператора Синтаксис Перегружаемый Примеры прототипов (для class T )
Внутри определения класса Вне определения класса
пре-инкремент ++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 ) ;
Примечания
  • Префиксные версии встроенных операторов возвращают ссылки , а постфиксные версии возвращают значения , и типичные пользовательские перегрузки следуют этой схеме, чтобы пользовательские операторы могли использоваться так же, как встроенные. Однако в пользовательской перегрузке оператора может использоваться любой тип в качестве возвращаемого типа (включая void ).
  • Параметр int является фиктивным параметром, используемым для различения префиксных и постфиксных версий операторов. При вызове пользовательского постфиксного оператора значение, передаваемое в этом параметре, всегда равно нулю, хотя оно может быть изменено путем вызова оператора с использованием нотации вызова функции (например, a. operator ++ ( 2 ) или operator ++ ( a, 2 ) ).

Содержание

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

Выражения префиксного инкремента и декремента имеют вид

++ выражение
-- выражение
1) префиксный инкремент (пре-инкремент)
2) префиксный декремент (пре-декремент)

Встроенные префиксные операторы

1) Выражение ++ x эквивалентно x + = 1 , за следующими исключениями:
  • Если тип выражения является (возможно, с volatile-квалификатором) bool , выражение устанавливается в true . Такое инкрементирование устарело.
(до C++17)
  • Если тип выражения является (возможно, cv-квалифицированным) bool , программа является некорректной.
(начиная с C++17)
  • Если тип выражения является volatile-квалифицированным, инкрементирование устарело.
(начиная с C++20)
2) Выражение -- x эквивалентно x - = 1 , за следующими исключениями:
  • Если тип выражения является (возможно cv-квалифицированным) bool , программа является некорректной.
  • Если тип выражения является volatile-квалифицированным, декремент устарел.
(since C++20)

Перегрузки

В разрешении перегрузки для пользовательских операторов , для каждого опционально volatile-квалифицированного арифметического типа A кроме bool , и для каждого опционально volatile-квалифицированного указателя P на опционально cv-квалифицированный объектный тип, следующие сигнатуры функций участвуют в разрешении перегрузки:

A & operator ++ ( A & )
bool & operator ++ ( bool & )
(устарело) (до C++17)
P & operator ++ ( P & )
A & operator -- ( A & )
P & operator -- ( P & )

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

Выражения постфиксного инкремента и декремента имеют вид

выражение ++
выражение --
1) постфиксный инкремент (постинкремент)
2) постфиксный декремент (пост-декремент)

Встроенные постфиксные операторы

Результатом постфиксного инкремента или декремента является значение, полученное применением преобразования lvalue-в-rvalue к expression (до модификации). Тип результата — это версия типа expression без cv-квалификаторов.

Если expression не является модифицируемым lvalue арифметического типа отличного от (возможно cv-квалифицированного) bool (since C++17) , или указателем на полный объектный тип, программа является некорректной.

Если тип expression квалифицирован как volatile, инкремент или декремент устарел.

(since C++20)
1) Значение выражения изменяется, как если бы оно было операндом префиксного оператора ++ .
2) Значение expression изменяется так, как если бы оно было операндом префиксного оператора -- .

Вычисление значения постфиксного инкремента или декремента упорядочено перед модификацией expression . По отношению к неопределённо упорядоченному вызову функции операция постфиксного инкремента или декремента является единым вычислением.

Перегрузки

В разрешении перегрузки для пользовательских операторов , для каждого опционально volatile-квалифицированного арифметического типа A , кроме bool , и для каждого опционально volatile-квалифицированного указателя P на опционально 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++ ++;   // ошибка
//  int n6 = n1 + ++n1; // неопределённое поведение
    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 -- , даже если эти операторы являются no-ops для конкретного итератора.

перегрузки для арифметических типов
увеличивает или уменьшает атомарное значение на единицу
(публичная функция-член 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 usual arithmetic conversions are applied for built-in pre-increment and
pre-decrement, but were not applied for their postfix counterparts [1]
also applied
CWG 2901 C++98 lvalue-to-rvalue conversions were not applied
for built-in post-increment and post-decrement
applied
  1. Префиксная форма ++ 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
Специальные операторы

static_cast преобразует один тип в другой связанный тип
dynamic_cast преобразует в пределах иерархий наследования
const_cast добавляет или удаляет cv -квалификаторы
reinterpret_cast преобразует тип в несвязанный тип
C-style приведение преобразует один тип в другой с помощью комбинации static_cast , const_cast и reinterpret_cast
new создает объекты с динамической продолжительностью хранения
delete уничтожает объекты, ранее созданные выражением new, и освобождает полученную область памяти
sizeof запрашивает размер типа
sizeof... запрашивает размер пакета (since C++11)
typeid запрашивает информацию о типе
noexcept проверяет, может ли выражение генерировать исключение (since C++11)
alignof запрашивает требования выравнивания типа (since C++11)

Документация по C для Операторы инкремента/декремента