C++函数调用实参的子表达式是否有序?Baz与Qux调用是否被排序?
关于C++函数实参求值顺序的疑问解答
给定函数声明
// 接受两个整数的函数 void AcceptTwoInts(int, int); // 接受整数并返回整数的两个函数 int Foo(int); int Bar(int); // 返回整数的两个函数 int Baz(); int Qux();
待分析的函数调用表达式
AcceptTwoInts(Foo(Baz()), Bar(Qux()));
核心问题
调用Baz相对于调用Qux是否被排序(即使是不确定排序)?是否可以假设:无论编译器选择哪种参数顺序,一个实参的所有子表达式都在另一个实参的子表达式开始求值前完成?(不考虑“as if”规则,仅讨论存在可观测差异的场景)
疑问依据
C++标准[expr.call]/7中的表述:
参数的初始化(包括所有相关的值计算和副作用),相对于其他任何参数的初始化,是不确定顺序的。
该表述存在两种可能解读:
- 存在保证:对于实参A和B,要么A的所有相关子表达式都在B的之前求值,反之亦然。
- 无保证:仅A和B的初始化步骤是不确定排序,不包含初始化涉及的子表达式。
正确解读
第一种解读是正确的,调用Baz属于初始化AcceptTwoInts第一个参数的“值计算”部分。
标准中明确说明参数初始化包括所有相关的值计算和副作用,Foo(Baz())作为第一个实参,其完整求值(包括Baz()的调用、Foo()的调用)都属于第一个参数初始化的关联操作;同理Bar(Qux())的完整求值属于第二个参数初始化的关联操作。这两组操作是不确定顺序的——要么第一个实参的所有子表达式都先完成,再求值第二个实参的所有子表达式;要么反过来。编译器不能交错执行这两组子表达式(比如先调用Baz(),再调用Qux(),再调用Foo(),最后调用Bar())。
换句话说,Baz和Qux的调用是被排序的,二者的执行顺序要么是Baz先于Qux,要么是Qux先于Baz,不存在交错执行的可能。
内容的提问来源于stack exchange,提问作者jacobsa
相关产品推荐
相关产品推荐

