Русская Википедия:Операторы в C и C++
Язык программирования C++ поддерживает все операторы своего прародителя Си и дополнен новыми операторами и возможностями.
- например, операторами приведения типа:
- возможность перегрузки операторов;
После вычисления первого операнда для неперегруженных операторов «&&», «||» и «,» (оператор «запятая», Шаблон:Lang-en) компилятор вставляет точку следования (Шаблон:Lang-en), гарантирующую, что все побочные эффекты (например, оператор «постфиксный ++») будут выполнены до начала вычисления второго операнда.
Языки с Си-подобным синтаксисом (например, Java, C#, PHP и другие) часто заимствуют операторы Cи/C++ с сохранением не только поведения, но также приоритета и ассоциативности.
Таблицы
В таблицах используются следующие обозначения:
- «a», «b» и «c»: имена объектов или значения (литералы, значения переменных, возвращаемые значения, lvalue);
- «Перегружаемый»: возможность перегрузки оператора в языке C++;
- «Реализован в Си»: существование оператора в языке Си;
- «R», «T», «S»: имена типов;
- «Пример»: пример объявления перегруженного оператора;
- «Член типа T»: определение оператора в виде метода структуры или класса (внутри структуры или класса); пример:
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
|
width="8%" Шаблон:Yes | width="8 %" Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Неравенство | != |
a != b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Больше | > |
a > b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Меньше | < |
a < b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Больше или равно | >= |
a >= b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Меньше или равно | <= |
a <= b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
Логические операторы
| Операция (выражение) | Оператор | Синтаксис выражения | Перегружаемый | Реализован в Си | Пример | |
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Логическое отрицание, НЕ | ! |
!a
|
width="8%" Шаблон:Yes | width="8 %" Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Логическое умножение, И | && |
a && b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Логическое сложение, ИЛИ | || |
a || b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
Побитовые операторы
| Операция (выражение) | Оператор | Синтаксис выражения | Перегружаемый | Реализован в Си | Пример | |
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Побитовая инверсия | ~ |
~a
|
width="8%" Шаблон:Yes | width="8 %" Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовое И | & |
a & b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовое ИЛИ (or) | | |
a | b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовое исключающее ИЛИ (xor) | ^ |
a ^ b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовый сдвиг влево[note 3] | << |
a << b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовый сдвиг вправо[note 3][note 4] | >> |
a >> b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
Составное присваивание
| Операция (выражение) | Оператор | Синтаксис выражения | Значение | Перегружаемый | Реализован в Си | Пример | |
|---|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | ||||||
| Сложение, совмещённое с присваиванием | += |
a += b
|
a = a + b
|
width="8%" Шаблон:Yes | width="8 %" Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Вычитание, совмещённое с присваиванием | -= |
a -= b
|
a = a - b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Умножение, совмещённое с присваиванием | *= |
a *= b
|
a = a * b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Деление, совмещённое с присваиванием | /= |
a /= b
|
a = a / b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Вычисление остатка от деления, совмещённое с присваиванием[note 1] | %= |
a %= b
|
a = a % b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовое «И» (AND), совмещённое с присваиванием | &= |
a &= b
|
a = a & b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовое «ИЛИ» (or), совмещённое с присваиванием | |= |
a |= b
|
a = a | b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовое «исключающее ИЛИ» (xor), совмещённое с присваиванием | ^= |
a ^= b
|
a = a ^ b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовый сдвиг влево, совмещённый с присваиванием | <<= |
a <<= b
|
a = a << b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
| Побитовый сдвиг вправо, совмещённый с присваиванием[note 4] | >>= |
a >>= b
|
a = a >> b
|
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp |
Операторы работы с указателями и членами класса
| Оператор | Синтаксис | Перегружаемый | Реализован в Си | Пример | ||
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Обращение к элементу массива | a[b]
|
width="8%" Шаблон:Yes | width="8 %" Шаблон:Yes | Шаблон:Cpp |
width="25%" Шаблон:N/a | |
| Непрямое обращение («объект, на который указывает a») | *a |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp | |
| Ссылка («адрес a») | &a |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp | |
| Обращение к члену структуры («член b объекта, на который указывает a») | a->b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp[note 5] |
Шаблон:N/a | |
| Обращение к члену структуры («член b объекта a») | a.b |
Шаблон:No | Шаблон:Yes | colspan="2" Шаблон:N/a | ||
| Член, на который указывает b в объекте, на который указывает a[note 6] | a->*b |
Шаблон:Yes | Шаблон:No | Шаблон:Cpp | Шаблон:Cpp | |
| Член, на который указывает b в объекте a | a.*b |
Шаблон:No | Шаблон:No | colspan="2" Шаблон:N/a | ||
Другие операторы
| Оператор | Синтаксис | Перегружаемый | Реализован в Си | Пример | ||
|---|---|---|---|---|---|---|
| Член типа T | Определение вне класса | |||||
| Функтор | a(a1, a2)
|
width="8%" Шаблон:Yes | width="8 %" Шаблон:Yes | Шаблон:Cpp | width="25%" Шаблон:N/a | |
| Оператор «запятая» | a, b |
Шаблон:Yes | Шаблон:Yes | Шаблон:Cpp | Шаблон:Cpp | |
| Тернарная условная операция | a ? b : c |
Шаблон:No | Шаблон:Yes | colspan="2" Шаблон:N/a | ||
| Оператор расширения области видимости | a::b |
Шаблон:No | Шаблон:No | colspan="2" Шаблон:N/a | ||
| Пользовательские литералы (введены в C++11) | "a"_b |
Шаблон:Yes | Шаблон:No | Шаблон:N/a | Шаблон:Cpp | |
| Sizeof (размер) | sizeof(a)[note 7]sizeof(type) |
Шаблон:No | Шаблон:Yes | colspan="2" Шаблон:N/a | ||
| Align-of (выравнивание) | alignof(type) или _Alignof(type)[note 8] |
Шаблон:No | Шаблон:Yes | colspan="2" Шаблон:N/a | ||
| Интроспекция | typeid(a)typeid(type) |
Шаблон:No | Шаблон:No | colspan="2" Шаблон:N/a | ||
| Приведение типа | (type) a |
rowspan="2" Шаблон:Yes | rowspan="2" Шаблон:Yes | Шаблон:Cpp | Шаблон:N/a | |
| [note 9] | ||||||
| Выделение памяти | new type |
Шаблон:Yes | Шаблон:No | Шаблон:Cpp | Шаблон:Cpp | |
| Выделение памяти для массива | new type[n] |
Шаблон:Yes | Шаблон:No | Шаблон:Cpp | Шаблон:Cpp | |
| Освобождение памяти | delete a |
Шаблон:Yes | Шаблон:No | Шаблон:Cpp | Шаблон:Cpp | |
| Освобождение памяти, занятой массивом | delete[] a |
Шаблон:Yes | Шаблон:No | Шаблон:Cpp | Шаблон:Cpp | |
Примечания: Шаблон:Примечания
Приоритеты операторов
В данной таблице указаны приоритеты операторов и их ассоциативность. Операторы, указанные в таблице выше (раньше), имеют более высокий приоритет (приоритет вычисления). При рассмотрении выражения, операторы, имеющие более высокий приоритет, будут вычислены раньше операторов с низким приоритетом. Если несколько операторов указаны в одной ячейке, то они имеют одинаковый приоритет и вычисляются в последовательности, задаваемой ассоциативностью. Приоритеты операторов не изменяются при их перегрузке.
Этой таблицы приоритетов в большинстве случаев бывает достаточно, за исключением следующих случаев. Тернарный оператор «?:» может содержать в среднем выражении оператор «запятая» или присваивание, но код «Шаблон:Cpp» компилятор воспринимает как «Шаблон:Cpp», а не как бессмысленное выражение «Шаблон:Cpp». Таким образом выражение между ? и : воспринимается, как если бы оно было в скобках.
| Приоритет | Оператор | Описание | Ассоциативность |
|---|---|---|---|
| 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 | ?:
|
Тернарная условная операция | Справа налево |
=
|
Присваивание | ||
+=
|
Сложение, совмещённое с присваиванием | ||
-=
|
Вычитание, совмещённое с присваиванием | ||
*=
|
Умножение, совмещённое с присваиванием | ||
/=
|
Деление, совмещённое с присваиванием | ||
%=
|
Вычисление остатка от деления, совмещённое с присваиванием | ||
<<=
|
Побитовый сдвиг влево, совмещённый с присваиванием | ||
>>=
|
Побитовый сдвиг вправо, совмещённый с присваиванием | ||
&=
|
Побитовое «И», совмещённое с присваиванием | ||
|=
|
Побитовое «ИЛИ», совмещённое с присваиванием | ||
^=
|
Побитовое «исключающее ИЛИ» (xor), совмещённое с присваиванием | ||
throw
|
Оператор создания исключения (C++) | ||
| 16 | ,
|
Оператор «запятая» | Слева направо |
Описание
Компилятор использует таблицу приоритетов для определения порядка вычисления операторов.
- Например,
++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
будет воспринято по-разному в этих двух языках. В Си выражение синтаксически некорректно, так как результат условного оператора не может служить lvalue (то есть, левой частью оператора присваивания).
В C++, выражение будет разобрано как корректное:[1]
e = (a < d ? a++ : (a = d))
Приоритеты побитовых логических операторов несколько неинтуитивны[2]. Концептуально & и | являются такими же арифметическими операторами как * и + соответственно.
Выражение Шаблон:Cpp синтаксически воспринимается как Шаблон:Cpp, но выражение Шаблон:Cpp эквивалентно Шаблон:Cpp. Из-за этого часто требуется пользоваться скобками для явного задания порядка вычислений.
Синонимы операторов в C++
В стандарте C++ определены[3] диграфы для некоторых операторов:
| Диграф | Эквивалентная строка |
|---|---|
| and | && |
| bitand | & |
| and_eq | &= |
| or | || |
| bitor | | |
| or_eq | |= |
| xor | ^ |
| xor_eq | ^= |
| not | ! |
| not_eq | != |
| compl | ~ |
Диграфы могут использоваться точно так же как и операторы, являются синонимами операторов. Например, диграф «Шаблон:Cpp» может использоваться для замены операторов «побитовое И» и «получение адреса» или в определении ссылочных типов. Так, код «Шаблон:Cpp» эквивалентен коду «Шаблон:Cpp».
Стандарт ANSI/ISO C определяет перечисленные диграфы в виде констант Шаблон:Cpp (см. препроцессор). Константы определены в заголовочном файле «iso646.h». Для совместимости с Си стандарт C++ определяет фиктивный заголовочный файл «ciso646».
Примечания
Ссылки
- Статья Шаблон:WaybackШаблон:Ref-en «Операторы C++» на сайте cppreference.com.
- Статья Шаблон:WaybackШаблон:Ref-en «Префиксные и постфиксные операторы в языках Си и C++» на сайте msdn.microsoft.com.
- ISO/IEC 14882
Шаблон:Rq Шаблон:Язык программирования Си
Ошибка цитирования Для существующих тегов <ref> группы «note» не найдено соответствующего тега <references group="note"/>
- Страницы, использующие устаревший тег source
- Русская Википедия
- Страницы с неработающими файловыми ссылками
- Язык программирования Си
- Синтаксис C++
- Операции в программировании
- Страницы, где используется шаблон "Навигационная таблица/Телепорт"
- Страницы с телепортом
- Википедия
- Статья из Википедии
- Статья из Русской Википедии
- Страницы с ошибками в примечаниях