命名空间
变体
操作

C++ 运算符优先级

来自 cppreference.com
< cpp‎ | language
 
 
C++ 语言
 
 

下表列出了 C++ 运算符的优先级和结合性。运算符按优先级从上到下排列。

优先级 运算符 描述 结合性
1 :: 作用域解析 左结合 →
2 a++   a-- 后缀/后置递增和递减
type()   type{} 函数风格强制转换
a() 函数调用
a[] 下标
.   -> 成员访问
3 ++a   --a 前缀/前置递增和递减 右结合 ←
+a   -a 一元/加号和减号
!   ~ 逻辑非按位非
(type) C 风格强制转换
*a 间接访问(解引用)
&a 取地址
sizeof sizeof[note 1]
co_await await 表达式 (C++20)
new   new[] 动态内存分配
delete   delete[] 动态内存释放
4 .*   ->* 指向成员的指针 左结合 →
5 a*b   a/b   a%b 乘法、除法和取模
6 a+b   a-b 加法和减法
7 <<   >> 按位/左移和右移
8 <=> 三元比较运算符 (自 C++20 起)
9 <   <=   >   >= 对于 关系运算符 < 和 ≤ 和 > 和 ≥ 分别
10 ==   != 对于 相等运算符 = 和 ≠ 分别
11 a&b 按位与
12 ^ 按位异或(异或)
13 | 按位或(或)
14 && 逻辑与
15 || 逻辑或
16 a?b:c 三元条件[note 2] 右结合 ←
throw 抛出运算符
co_yield yield 表达式 (C++20)
= 直接赋值(默认情况下为 C++ 类提供)
+=   -= 复合赋值 通过求和和求差
*=   /=   %= 复合赋值 通过乘积、商和余数
<<=   >>= 复合赋值 通过按位左移和右移
&=   ^=   |= 复合赋值 通过按位与、异或和或
17 , 逗号 左结合 →
  1. sizeof 的操作数不能是 C 样式类型转换:表达式 sizeof (int) * p 被明确地解释为 (sizeof(int)) * p,而不是 sizeof((int)*p)
  2. 条件运算符(?: 之间的表达式)被解析为括号内的表达式:它相对于 ?: 的优先级被忽略。

解析表达式时,表中某行具有优先级的运算符将比位于该行下方且具有较低优先级的任何运算符更紧密地绑定到其参数(就好像由括号括起来一样)。例如,表达式 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 ++*pdelete(++(*p))),而一元后缀运算符始终从左到右结合(a[1][2]++((a[1])[2])++)。注意,结合性对于成员访问运算符是有意义的,即使它们与一元后缀运算符分组:a.b++ 被解析为 (a.b)++,而不是 a.(b++)

运算符优先级不受 运算符重载 影响。例如,std::cout << a ? b : c; 被解析为 (std::cout << a) ? b : c;,因为算术左移的优先级高于条件运算符。

[edit] 注意

优先级和结合性是编译时概念,与 求值顺序 无关,求值顺序是运行时概念。

标准本身没有指定优先级级别。它们是从语法推导出来的。

const_caststatic_castdynamic_castreinterpret_casttypeidsizeof...noexceptalignof 没有被包含,因为它们永远不会引起歧义。

某些运算符具有 替代拼写(例如,&&and||or!not 等)。

在 C 中,三元条件运算符的优先级高于赋值运算符。因此,表达式 e = a < d ? a++ : a = d,它在 C++ 中被解析为 e = ((a < d) ? (a++) : (a = d)),将在 C 中因语法或语义限制而无法编译。有关详细信息,请参见相应的 C 页面。

[edit] 另请参阅

常用运算符
赋值 递增
递减
算术 逻辑 比较 成员
访问
其他

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
特殊运算符

static_cast 将一种类型转换为另一种相关类型
dynamic_cast 在继承层次结构内转换
const_cast 添加或删除 cv 限定符
reinterpret_cast 将类型转换为不相关的类型
C 样式转换 通过混合使用 static_castconst_castreinterpret_cast 将一种类型转换为另一种类型
new 创建具有动态存储期的对象
delete 销毁以前由 new 表达式创建的对象并释放获取的内存区域
sizeof 查询类型的尺寸
sizeof... 查询 参数包 的尺寸 (自 C++11 起)
typeid 查询类型的类型信息
noexcept 检查表达式是否可以抛出异常 (自 C++11 起)
alignof 查询类型的对齐要求 (自 C++11 起)

C 文档 针对 C 运算符优先级