C++ Operator Precedence
В следующей таблице перечислены приоритет и ассоциативность операторов C++. Операторы перечислены сверху вниз в порядке убывания приоритета. a , b и c являются операндами.
| Приоритет | Оператор | Описание | Ассоциативность |
|---|---|---|---|
| 1 | a :: b | Разрешение области видимости | Слева направо → |
| 2 | a ++ a -- | Постфиксные инкремент и декремент | |
type
(
a
)
type
{
a
}
|
Функциональное приведение | ||
| a ( ) | Вызов функции | ||
| a [ ] | Оператор индексации | ||
| a. b a - > b | Доступ к члену | ||
| 3 | ++ a -- a | Префиксные инкремент и декремент | Справа налево ← |
| + a - a | Унарные плюс и минус | ||
| ! a ~a | Логическое НЕ и побитовое НЕ | ||
(
type
)
a
|
C-style cast | ||
(
type
)
a
|
Приведение в стиле C | ||
| * a | Разыменование (dereference) | ||
| & a | Взятие адреса | ||
sizeof
|
Оператор sizeof [примечание 1] | ||
| co_await | выражение ожидания (C++20) | ||
new
–
new[]
|
Динамическое выделение памяти | ||
delete
–
delete[]
|
Освобождение динамической памяти | ||
| 4 | a. * b a - > * b | Указатель на член | Слева направо → |
| 5 | a * b a / b a % b | Умножение, деление и остаток от деления | |
| 6 | a + b a - b | Сложение и вычитание | |
| 7 | a << b a >> b | Побитовый сдвиг влево и сдвиг вправо | |
| 8 | a <=> b | Оператор трёхстороннего сравнения (начиная с C++20) | |
| 9 | a < b a <= b a > b a >= b |
Для
операторов сравнения
<
и
<=
и
>
и
>=
соответственно
|
|
| 10 | a == b a ! = b |
Для
операторов сравнения
=
и
!=
соответственно
|
|
| 11 | a & b | Побитовое И | |
| 12 | a ^ b | Побитовое исключающее ИЛИ (исключающее или) | |
| 13 | a | b | Побитовое ИЛИ (включающее ИЛИ) | |
| 14 | a && b | Логическое И | |
| 15 | a || b | Логическое ИЛИ | |
| 16 | a ? b : c | Тернарный условный оператор [примечание 2] | Справа налево ← |
throw
|
оператор throw | ||
| co_yield | выражение yield (C++20) | ||
| a = b | Прямое присваивание (предоставляется по умолчанию для классов C++) | ||
| a + = b a - = b | Составное присваивание сложением и вычитанием | ||
| a * = b a / = b a % = b | Составное присваивание произведением, частным и остатком | ||
| a <<= b a >>= b | Составное присваивание побитовым сдвигом влево и вправо | ||
| a & = b a ^ = b a | = b | Составное присваивание побитовыми И, исключающим ИЛИ и ИЛИ | ||
| 17 | a, b | Запятая | Слева направо → |
- ↑ Операнд оператора sizeof не может быть C-приведением типа: выражение sizeof ( int ) * p однозначно интерпретируется как ( sizeof ( int ) ) * p , но не как sizeof ( ( int ) * p ) .
-
↑
Выражение в середине условного оператора (между
?и:) анализируется как если бы оно было в скобках: его приоритет относительно?:игнорируется.
При разборе выражения оператор, который указан в некоторой строке приведенной выше таблицы с определенным приоритетом, будет связываться теснее (как если бы были расставлены скобки) со своими аргументами, чем любой оператор, указанный в строке ниже с более низким приоритетом. Например, выражения std:: cout << a & b и * p ++ разбираются как ( std:: cout << a ) & b и * ( p ++ ) , а не как std:: cout << ( a & b ) или ( * p ) ++ .
Операторы с одинаковым приоритетом связываются со своими аргументами в направлении их ассоциативности. Например, выражение a = b = c разбирается как a = ( b = c ) , а не как ( a = b ) = c из-за правосторонней ассоциативности присваивания, но a + b - c разбирается как ( a + b ) - c , а не a + ( b - c ) из-за левосторонней ассоциативности сложения и вычитания.
Спецификация ассоциативности избыточна для унарных операторов и приводится только для полноты: унарные префиксные операторы всегда ассоциируют справа налево ( delete ++* p это delete ( ++ ( * p ) ) ), а унарные постфиксные операторы всегда ассоциируют слева направо ( a [ 1 ] [ 2 ] ++ это ( ( a [ 1 ] ) [ 2 ] ) ++ ). Заметьте, что ассоциативность значима для операторов доступа к членам, хотя они группируются с унарными постфиксными операторами: a. b ++ парсится как ( a. b ) ++ , а не как a. ( b ++ ) .
Приоритет операторов не изменяется при перегрузке операторов . Например, std:: cout << a ? b : c ; разбирается как ( std:: cout << a ) ? b : c ; поскольку приоритет арифметического левого сдвига выше, чем у условного оператора.
Примечания
Приоритет и ассоциативность являются концепциями времени компиляции и не зависят от порядка вычисления , который является концепцией времени выполнения.
Сам стандарт не определяет уровни приоритета. Они выводятся из грамматики.
const_cast
,
static_cast
,
dynamic_cast
,
reinterpret_cast
,
typeid
,
sizeof...
,
noexcept
и
alignof
не включены, поскольку они никогда не являются неоднозначными.
Некоторые операторы имеют альтернативные написания (например, and для && , or для || , not для ! и т.д.).
В языке C тернарный условный оператор имеет более высокий приоритет, чем операторы присваивания. Поэтому выражение e = a < d ? a ++ : a = d , которое в C++ разбирается как e = ( ( a < d ) ? ( a ++ ) : ( a = d ) ) , не будет компилироваться в C из-за грамматических или семантических ограничений в C. Подробности смотрите на соответствующей странице для C.
Смотрите также
| Основные операторы | ||||||
|---|---|---|---|---|---|---|
| присваивание |
инкремент
декремент |
арифметические | логические | сравнения |
доступа к членам
|
прочие |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
...
]
|
вызов функции
a ( ... ) |
|
запятая
a, b |
||||||
|
условный оператор
a ? b : c |
||||||
| Специальные операторы | ||||||
|
static_cast
преобразует один тип в другой связанный тип
|
||||||
|
C documentation
для
C operator precedence
|