C++左结合,右结合的概念,与运算符的优先级有什么关系
什么是结合性?
结合性决定了当同一个表达式中出现多个相同优先级的运算符时,运算的执行顺序。
它主要解决两种问题:
- 左结合:从左向右计算。
- 右结合:从右向左计算。
左结合
大多数运算符是左结合的。这意味着运算从表达式的最左边开始。
例子:a - b - c
- 运算符
-是左结合的。 - 它被解释为
(a - b) - c。 - 先计算
a - b,然后用其结果减去c。
其他左结合运算符的例子:
a + b + c→(a + b) + ca * b * c→(a * b) * ca / b / c→(a / b) / ca && 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 | , |
逗号运算符 | 从左到右 |
重要说明
-
结合性:
- 大部分从左到右
- 一元、赋值、条件运算符从右到左
-
记忆技巧:
- 算术 > 移位 > 比较 > 位运算 > 逻辑 > 条件 > 赋值 > 逗号
- 一元运算符优先级很高
- 后缀高于前缀
-
最佳实践:
- 不确定时使用括号明确优先级
- 避免编写过于复杂的表达式