结合性仅决定相同优先级运算符的语法分组方式,不决定运行时求值顺序;例如a = b = c被解析为a = (b = c),但b、c的求值顺序未定义。

结合性不决定计算顺序,只决定操作数和运算符怎么分组。很多人写 a = b = c 或 a + b + c 时以为“从左到右算”或“从右到左算”是编译器执行的步骤,其实不是——它只是语法解析阶段对表达式结构的约定,跟运行时求值顺序无关。
结合性只影响语法树的构造方式
比如 a = b = c 是右结合,意味着解析器把它看作 a = (b = c),而不是 (a = b) = c。这决定了:
- b = c 必须先完成(否则 a 没东西可赋)
- 整个表达式的类型和值由最内层赋值决定(b = c 的结果再赋给 a)
但注意:这不保证 b 和 c 的取值谁先发生。如果 b 是函数调用,c 是另一个函数调用,它们的执行顺序仍是未定义的(除非用逗号运算符或序列点约束)。
计算顺序由求值顺序规则和运算符语义决定
C++ 标准明确区分了“分组”和“求值”。以下才是影响实际执行顺序的关键:
- && 和 || 有短路求值:左侧为假时,右侧根本不会求值
- ?: 只求被选中的分支(cond ? A : B 中,A 和 B 不会都执行)
- 逗号运算符 , 强制从左到右求值,且左侧结果被丢弃
- 函数调用中,所有参数的求值顺序是未指定的(f(g(), h()) 中 g() 和 h() 谁先调用不确定)
- 复合赋值如 a += b 等价于 a = a + b,但 a 只求值一次(这是语义保证,不是结合性带来的)
最容易混淆的典型场景
这些例子常被误读为“结合性导致的执行顺序”:
- i++ + ++i:这不是结合性问题,而是未定义行为——同一表达式里对 i 两次修改且无序列点
- *p++:右结合性让它被解析为 *(p++),但 p++ 的副作用(p 自增)何时生效、* 解引用用的是旧地址还是新地址,取决于求值顺序,C++17 之前未指定
- a :虽然 <code>&& 左结合,但真正起作用的是短路语义——c 是否执行,只取决于 <code>a 的结果,和结合性无关
真正需要警惕的,从来不是“哪个运算符先结合”,而是“哪些子表达式可能并行/乱序求值”。加括号能解决分组歧义,但不能控制求值顺序;要控制顺序,得靠运算符本身的语义(如 ,、&&)、显式序列点(如函数调用前后),或者 C++17 引入的更严格的求值顺序规则。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











