Приоритет операторов C++
В следующей таблице приведены приоритет и ассоциативность операторов 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 | ||
*a
|
Разыменование (dereference) | ||
&a
|
Взятие адреса | ||
^^a
|
Оператор рефлексии (начиная с C++26) | ||
sizeof
|
Размер[1] | ||
| co_await | 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
|
Побитовое исключающее ИЛИ (exclusive or) | |
| 13 | a | b
|
Побитовое включающее ИЛИ (inclusive or) | |
| 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
|