Язык программирования C++, поддерживает все операторы своего прародителя Си и дополнен новыми операторами и возможностями.
После вычисления первого операнда для неперегруженных операторов «&&», «||» и «,» (оператор «запятая», англ. comma) компилятор вставляет точку следования (англ. sequence point), гарантирующую, что все побочные эффекты (например, оператор «постфиксный ++») будут выполнены до начала вычисления второго операнда.
Языки с Си-подобным синтаксисом (например, Java, C#, PHP и другие) часто заимствуют операторы Cи/C++ с сохранением не только поведения, но также приоритета и ассоциативности.
В таблицах используются следующие обозначения:
struct T { // или class
operator float () const;
};
T::operator float () const { /* реализация */ };
#include <iostream>
struct T { // или class
/* ... */
};
std::ostream & operator << ( std::ostream & a, T const & b ) { /* реализация */ }
| Операция (выражение) | Оператор | Синтаксис выражения | Перегружаемый | Реализован в Си | Пример | ||
|---|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | ||||||
| Присваивание | = | a = b | Да | Да | R& T::operator =(S b);
|
н/д | |
| Сложение | + | a + b | Да | Да | R T::operator +(S b);
|
R operator +(T a, S b);
| |
| Вычитание | - | a - b | Да | Да | R T::operator -(S b);
|
R operator -(T a, S b);
| |
| Унарный плюс | + | +a | Да | Да | R T::operator +();
|
R operator +(T a);
| |
| Унарный минус | - | -a | Да | Да | R T::operator -();
|
R operator -(T a);
| |
| Умножение | * | a * b | Да | Да | R T::operator *(S b);
|
R operator *(T a, S b);
| |
| Деление | / | a / b | Да | Да | R T::operator /(S b);
|
R operator /(T a, S b);
| |
| Операция модуль (остаток от деления целых чисел)[note 1] | % | a % b | Да | Да | R T::operator %(S b);
|
R operator %(T a, S b);
| |
| Инкремент | префиксный | ++ |
++a |
Да | Да | R& T::operator ++();
|
R& operator ++(T a);
|
| суффиксный (постфиксный) | ++ |
a++ |
Да | Да | R T::operator ++(int);
|
R operator ++(T a, int);
| |
| [note 2] | |||||||
| Декремент | префиксный | -- |
--a | Да | Да | R& T::operator --();
|
R& operator --(T a);
|
| суффиксный (постфиксный) | -- |
a-- | Да | Да | R T::operator --(int);
|
R operator --(T a, int);
| |
| [note 2] | |||||||
| Операция (выражение) | Оператор | Синтаксис выражения | Перегружаемый | Реализован в Си | Пример | |
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Равенство | == | a == b |
Да | Да | R T::operator ==(S b);
|
R operator ==(T a, S b);
|
| Неравенство | != | a != b | Да | Да | R T::operator !=(S b);
|
R operator !=(T a, S b);
|
| Больше | > | a > b | Да | Да | R T::operator >(S b);
|
R operator >(T a, S b);
|
| Меньше | < | a < b | Да | Да | R T::operator <(S b);
|
R operator <(T a, S b);
|
| Больше или равно | >= | a >= b | Да | Да | R T::operator >=(S b);
|
R operator >=(T a, S b);
|
| Меньше или равно | <= | a <= b | Да | Да | R T::operator <=(S b);
|
R operator <=(T a, S b);
|
| Операция (выражение) | Оператор | Синтаксис выражения | Перегружаемый | Реализован в Си | Пример | |
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Логическое отрицание, НЕ | ! | !a |
Да | Да | R T::operator !();
|
R operator !(T a);
|
| Логическое умножение, И | && | a && b | Да | Да | R T::operator &&(S b);
|
R operator &&(T a, S b);
|
| Логическое сложение, ИЛИ | || | a || b | Да | Да | R T::operator ||(S b);
|
R operator ||(T a, S b);
|
| Операция (выражение) | Оператор | Синтаксис выражения | Перегружаемый | Реализован в Си | Пример | |
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Побитовая инверсия | ~ | ~a |
Да | Да | R T::operator ~();
|
R operator ~(T a);
|
| Побитовое И | & | a & b | Да | Да | R T::operator &(S b);
|
R operator &(T a, S b);
|
| Побитовое ИЛИ (or) | | | a | b | Да | Да | R T::operator |(S b);
|
R operator |(T a, S b);
|
| Побитовое исключающее ИЛИ (xor) | ^ | a ^ b | Да | Да | R T::operator ^(S b);
|
R operator ^(T a, S b);
|
| Побитовый сдвиг влево[note 3] | << | a << b | Да | Да | R T::operator <<(S b);
|
R operator <<(T a, S b);
|
| Побитовый сдвиг вправо[note 3][note 4] | >> | a >> b | Да | Да | R T::operator >>(S b);
|
R operator >>(T a, S b);
|
| Операция (выражение) | Оператор | Синтаксис выражения | Значение | Перегружаемый | Реализован в Си | Пример | |
|---|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | ||||||
| Сложение, совмещённое с присваиванием | += | a += b |
a = a + b |
Да | Да | R T::operator +=(S b);
|
R operator +=(T a, S b);
|
| Вычитание, совмещённое с присваиванием | -= | a -= b |
a = a - b |
Да | Да | R T::operator -=(S b);
|
R operator -=(T a, S b);
|
| Умножение, совмещённое с присваиванием | *= | a *= b |
a = a * b |
Да | Да | R T::operator *=(S b);
|
R operator *=(T a, S b);
|
| Деление, совмещённое с присваиванием | /= | a /= b |
a = a / b |
Да | Да | R T::operator /=(S b);
|
R operator /=(T a, S b);
|
| Вычисление остатка от деления, совмещённое с присваиванием[note 1] | %= | a %= b |
a = a % b |
Да | Да | R T::operator %=(S b);
|
R operator %=(T a, S b);
|
| Побитовое «И» (AND), совмещённое с присваиванием | &= | a &= b |
a = a & b |
Да | Да | R T::operator &=(S b);
|
R operator &=(T a, S b);
|
| Побитовое «ИЛИ» (or), совмещённое с присваиванием | |= | a |= b |
a = a | b |
Да | Да | R T::operator |=(S b);
|
R operator |=(T a, S b);
|
| Побитовое «исключающее ИЛИ» (xor), совмещённое с присваиванием | ^= | a ^= b |
a = a ^ b |
Да | Да | R T::operator ^=(S b);
|
R operator ^=(T a, S b);
|
| Побитовый сдвиг влево, совмещённый с присваиванием | <<= | a <<= b |
a = a << b |
Да | Да | R T::operator <<=(S b);
|
R operator <<=(T a, S b);
|
| Побитовый сдвиг вправо, совмещённый с присваиванием[note 4] | >>= | a >>= b |
a = a >> b |
Да | Да | R T::operator >>=(S b);
|
R operator >>=(T a, S b);
|
| Оператор | Синтаксис | Перегружаемый | Реализован в Си | Пример | ||
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Обращение к элементу массива | a[b] |
Да | Да | R T::operator [](S b);
|
н/д | |
| Непрямое обращение («объект, на который указывает a») | *a | Да | Да | R T::operator *();
|
R operator *(T a);
| |
| Ссылка («адрес a») | &a | Да | Да | R T::operator &();
|
R operator &(T a);
| |
| Обращение к члену структуры («член b объекта, на который указывает a») | a->b | Да | Да | R* T::operator ->();
[note 5] |
н/д | |
| Обращение к члену структуры («член b объекта a») | a.b | Нет | Да | н/д | ||
| Член, на который указывает b в объекте, на который указывает a[note 6] | a->*b | Да | Нет | R T::operator ->*(S b);
|
R operator ->*(T a, S b);
| |
| Член, на который указывает b в объекте a | a.*b | Нет | Нет | н/д | ||
| Оператор | Синтаксис | Перегружаемый | Реализован в Си | Пример | ||
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Функтор | a(a1, a2) |
Да | Да | R T::operator ()(S a1, U a2, ...);
|
н/д | |
| Оператор «запятая» | a, b | Да | Да | R T::operator ,(S b);
|
R operator ,(T a, S b);
| |
| Тернарная условная операция | a ? b : c | Нет | Да | н/д | ||
| Оператор расширения области видимости | a::b | Нет | Нет | н/д | ||
| Sizeof (размер) | sizeof(a)[note 7]sizeof(type) | Нет | Да | н/д | ||
| Align-of (выравнивание) | alignof(type) или _Alignof(type)[note 8] | Нет | Да | н/д | ||
| Интроспекция | typeid(a)typeid(type) | Нет | Нет | н/д | ||
| Приведение типа | (type) a | Да | Да | T::operator R();
|
н/д | |
| [note 9] | ||||||
| Выделение памяти | new type | Да | Нет | void* T::operator new(size_t x);
|
void* operator new(size_t x);
| |
| Выделение памяти для массива | new type[n] | Да | Нет | void* T::operator new[](size_t x);
|
void* operator new[](size_t x);
| |
| Освобождение памяти | delete a | Да | Нет | void T::operator delete(void* x);
|
void operator delete(void* x);
| |
| Освобождение памяти, занятой массивом | delete[] a | Да | Нет | void T::operator delete[](void* x);
|
void operator delete[](void* x);
| |
Примечания:
fmod
() из файла «math.h».int
. Часто этому параметру даже не дают имя.<<
» и «>>
» используются для работы с потоковым выводом и вводом.operator->()
» должен быть типом, к которому применим оператор «->
», например, указателем. Если «x
» имеет тип «C
», и класс «C
» перегружает оператор «operator->()
», выражение «x->y
» раскрывается как «x.operator->()->y
».->* для умных указателей» Скотта Майерса из журнала «Dr. Dobb’s journal», выпуск за октябрь 1999 года.sizeof
, обычно, записывают со скобками. Если операнд — имя переменной, указание скобок необязательно. Если операнд — имя типа, скобки обязательны.alignof. Аналогичный оператор в стандарте языка Си называется _Alignof.В данной таблице указаны приоритеты операторов и их ассоциативность. Операторы, указанные в таблице выше (раньше), имеют более высокий приоритет (приоритет вычисления). При рассмотрении выражения, операторы, имеющие более высокий приоритет, будут вычислены раньше операторов с низким приоритетом. Если несколько операторов указаны в одной ячейке, то они имеют одинаковый приоритет и вычисляются в последовательности, задаваемой ассоциативностью. Приоритеты операторов не изменяются при их перегрузке.
Этой таблицы приоритетов в большинстве случаев бывает достаточно, за исключением следующих случаев. Тернарный оператор «?:» может содержать в среднем выражении оператор «запятая» или присваивание, но код «a ? b, c : d
» компилятор воспринимает как «a ? (b, c) : d
», а не как бессмысленное выражение «(a ? b), (c : d)
». Таким образом выражение между ? и : воспринимается, как если бы оно было в скобках.
| Приоритет | Оператор | Описание | Ассоциативность |
|---|---|---|---|
| 1
Наивысший |
:: |
Раскрытие области видимости | Нет |
| 2 | ++ |
Суффиксный инкремент | Слева направо |
-- |
Суффиксный декремент | ||
() |
Вызов функции | ||
[] |
Взятие элемента массива | ||
. |
Выбор элемента по ссылке | ||
-> |
Выбор элемента по указателю | ||
typeid() |
RTTI (только C++; см typeid) | ||
const_cast |
Приведение типа (C++) (см const cast) | ||
dynamic_cast |
Приведение типа (C++) (см dynamic cast) | ||
reinterpret_cast |
Каламбур типизации (C++) (см reinterpret_cast) | ||
static_cast |
Приведение типа (C++) (см static cast) | ||
| 3 | ++ |
Префиксный инкремент | Справа налево |
-- |
Префиксный декремент | ||
+ |
Унарный плюс | ||
- |
Унарный минус | ||
! |
Логическое НЕ | ||
~ |
Побитовое НЕ | ||
(type) |
Приведение типа | ||
* |
Разыменование указателя | ||
& |
Взятие адреса объекта | ||
sizeof |
Sizeof (размер) | ||
new, new[] |
Выделение динамической памяти (C++) | ||
delete, delete[] |
Освобождение динамической памяти (C++) | ||
| 4 | .* |
Указатель на член (C++) | Слева направо |
->* |
Указатель на член (C++) | ||
| 5 | * |
Умножение | |
/ |
Деление | ||
% |
Получение остатка от деления | ||
| 6 | + |
Сложение | |
- |
Вычитание | ||
| 7 | << |
Побитовый сдвиг влево | |
>> |
Побитовый сдвиг вправо | ||
| 8 | < |
Меньше | |
<= |
Меньше или равно | ||
> |
Больше | ||
>= |
Больше или равно | ||
| 9 | == |
Равенство | |
!= |
Неравенство | ||
| 10 | & |
Побитовое И (and) | |
| 11 | ^ |
Побитовое исключающее ИЛИ (xor) | |
| 12 | | |
Побитовое ИЛИ (or) | |
| 13 | && |
Логическое И | |
| 14 | || |
Логическое ИЛИ | |
| 15 | ?: |
Тернарная условная операция | Справа налево |
| 16 | = |
Присваивание | |
+= |
Сложение, совмещённое с присваиванием | ||
-= |
Вычитание, совмещённое с присваиванием | ||
*= |
Умножение, совмещённое с присваиванием | ||
/= |
Деление, совмещённое с присваиванием | ||
%= |
Вычисление остатка от деления, совмещённое с присваиванием | ||
<<= |
Побитовый сдвиг влево, совмещённый с присваиванием | ||
>>= |
Побитовый сдвиг вправо, совмещённый с присваиванием | ||
&= |
Побитовое «И», совмещённое с присваиванием | ||
|= |
Побитовое «ИЛИ», совмещённое с присваиванием | ||
^= |
Побитовое «исключающее ИЛИ» (xor), совмещённое с присваиванием | ||
| 17 | throw |
Оператор создания исключения (C++) | |
| 18 | , |
Оператор «запятая» | Слева направо |
Компилятор использует таблицу приоритетов для определения порядка вычисления операторов.
++x*3 был бы двусмысленным без каких-либо правил приоритетов. По таблице можно сказать, что x сначала связывается с оператором ++, и только затем с оператором *, поэтому независимо от действия оператора ++, это действие только над x (а не над x*3). Таким образом, выражение эквивалентно (++x, x*3).3*x++, где таблица утверждает, что инкремент применяется только к x а не к 3*x. Функционально это выражение эквивалентно (tmp=x, x++, tmp=3*tmp, tmp), если выразить временную переменную как tmp.
Связывание операторов в стандартах Си и C++ определено через грамматику языка, а не через таблицу. Это может создать конфликт. Например, в языке Си синтаксис условного оператора таков:
logical-OR-expression ? expression : conditional-expression
А в языке C++:
logical-OR-expression ? expression : assignment-expression
Из-за этого выражение:
e = a < d ? a++ : a = d
будет воспринято по-разному в этих двух языках. В Си выражение синтаксически некорректно, но многие компиляторы воспринимают его как:
e = ((a < d ? a++ : a) = d)
Этот вариант ошибочен, так как результат условного оператора не может служить lvalue (то есть, левой частью оператора присваивания).
В C++, выражение будет разобрано как корректное:
e = (a < d ? a++ : (a = d))
Приоритеты побитовых логических операторов несколько неинтуитивны[1]. Концептуально & и | являются такими же арифметическими операторами как * и + соответственно.
Выражение a & b == 7
синтаксически воспринимается как a & (b == 7)
, но выражение a + b == 7
эквивалентно (a + b) == 7
. Из-за этого часто требуется пользоваться скобками для явного задания порядка вычислений.
В стандарте C++ определены[2] диграфы для некоторых операторов:
| Диграф | Эквивалентная строка |
|---|---|
| and | && |
| bitand | & |
| and_eq | &= |
| or | || |
| bitor | | |
| or_eq | |= |
| xor | ^ |
| xor_eq | ^= |
| not | ! |
| not_eq | != |
| compl | ~ |
Диграфы могут использоваться точно так же как и операторы, являются синонимами операторов. Например, диграф «bitand
» может использоваться для замены операторов «побитовое И» и «получение адреса» или в определении ссылочных типов. Так, код «int bitand ref = n;
» эквивалентен коду «int & ref = n;
».
Стандарт ANSI/ISO C определяет перечисленные диграфы в виде констант #define
(см. препроцессор). Константы определены в заголовочном файле «iso646.h». Для совместимости с Си стандарт C++ определяет фиктивный заголовочный файл «ciso646».
Для улучшения этой статьи желательно: |
Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .