Приоритет операторов 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 | Косвенная адресация (разыменование) | ||
&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 | Побитовое исключающее ИЛИ (исключающее ИЛИ) | |
| 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 += 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 |
||||||
| Специальные операторы | ||||||
|
|
||||||
| Документация по C о приоритете операторов C |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/operator_precedence