C++左结合,右结合的概念,与运算符的优先级有什么关系
什么是结合性?
结合性决定了当同一个表达式中出现多个相同优先级的运算符时,运算的执行顺序。
它主要解决两种问题:
- 左结合:从左向右计算。
- 右结合:从右向左计算。
左结合
大多数运算符是左结合的。这意味着运算从表达式的最左边开始。
例子:a - b - c
- 运算符
-
是左结合的。 - 它被解释为
(a - b) - c
。 - 先计算
a - b
,然后用其结果减去c
。
其他左结合运算符的例子:
a + b + c
→(a + b) + c
a * b * c
→(a * b) * c
a / b / c
→(a / b) / c
a && b && c
→(a && b) && c
右结合
少数运算符是右结合的。这意味着运算从表达式的最右边开始。
例子1:a = b = c
- 运算符
=
是右结合的。 - 它被解释为
a = (b = c)
。 - 先执行
b = c
,然后将这个赋值表达式的结果(即c
的值)再赋给a
。
例子2:*p++
- 这里
*
和++
(后缀)优先级相同,但它们是右结合的。 - 它被解释为
*(p++)
,而不是(*p)++
。先执行p++
,然后对自增前的地址解引用。
其他右结合运算符的例子:
!~a
→!(~a)
(一元运算符)a ? b : c ? d : e
→a ? b : (c ? d : e)
(条件运算符)
结合性与优先级的关系
这是一个关键区别:
特性 | 优先级 | 结合性 |
---|---|---|
解决的问题 | 不同运算符之间,谁先执行? | 相同优先级的运算符之间,谁先执行? |
类比 | 乘法和加法,先算乘法 | 多个连加的加法,从左往右算 |
例子 | a + b * c → a + (b * c) |
a + b + c → (a + b) + c |
总结关系:
- 优先级第一:首先根据优先级确定哪些操作先绑定。
- 结合性第二:当优先级无法决定顺序时(即运算符相同时),再用结合性来决定。
经典示例分析
x = a + b * c > d && e || f
- 优先级最高:
*
→b * c
- 优先级次高:
+
→a + (b * c)
- 优先级第三:
>
→(a + b * c) > d
- 优先级第四:
&&
→((a + b * c) > d) && e
- 优先级第五:
||
(左结合) →[((a + b * c) > d) && e] || f
- 优先级最低:
=
(右结合) →x = ([((a + b * c) > d) && e] || f)
最终等价于:x = ( ( (a + (b * c)) > d ) && e ) || f )
核心要点
- 优先级解决“先乘除后加减”的问题。
- 结合性解决“多个相同运算符如何分组”的问题。
- 当不确定时,使用括号是确保表达式按你意图执行的最佳实践。
运算符优先级表
优先级 | 运算符 | 描述 | 结合性 |
---|---|---|---|
1 | :: |
作用域解析 | 从左到右 |
2 | a++ a-- |
后缀自增/自减 | 从左到右 |
type() type{} |
函数风格转换 | 从左到右 | |
a() |
函数调用 | 从左到右 | |
a[] |
下标 | 从左到右 | |
. -> |
成员访问 | 从左到右 | |
3 | ++a --a |
前缀自增/自减 | 从右到左 |
+a -a |
一元正负 | 从右到左 | |
! ~ |
逻辑非、按位非 | 从右到左 | |
(type) |
C风格转换 | 从右到左 | |
*a |
解引用 | 从右到左 | |
&a |
取地址 | 从右到左 | |
sizeof |
大小查询 | 从右到左 | |
new new[] delete delete[] |
动态内存 | 从右到左 | |
4 | .* ->* |
成员指针访问 | 从左到右 |
5 | * / % |
乘、除、取模 | 从左到右 |
6 | + - |
加、减 | 从左到右 |
7 | << >> |
位左移、右移 | 从左到右 |
8 | <=> |
三路比较(C++20) | 从左到右 |
9 | < <= > >= |
关系比较 | 从左到右 |
10 | == != |
相等比较 | 从左到右 |
11 | & |
按位与 | 从左到右 |
12 | ^ |
按位异或 | 从左到右 |
13 | | |
按位或 | 从左到右 |
14 | && |
逻辑与 | 从左到右 |
15 | || |
逻辑或 | 从左到右 |
16 | ?: |
条件运算符 | 从右到左 |
= |
赋值 | 从右到左 | |
+= -= *= /= %= |
复合赋值 | 从右到左 | |
<<= >>= |
位运算复合赋值 | 从右到左 | |
&= ^= |= |
位运算复合赋值 | 从右到左 | |
17 | , |
逗号运算符 | 从左到右 |
重要说明
-
结合性:
- 大部分从左到右
- 一元、赋值、条件运算符从右到左
-
记忆技巧:
- 算术 > 移位 > 比较 > 位运算 > 逻辑 > 条件 > 赋值 > 逗号
- 一元运算符优先级很高
- 后缀高于前缀
-
最佳实践:
- 不确定时使用括号明确优先级
- 避免编写过于复杂的表达式