C++中foo().bar()里foo()调用是否必然早于bar()?标准依据何在?
问题分析与解答
先给出代码示例:
struct Foo { static void bar(); }; Foo foo() { return Foo(); }
核心问题
在表达式foo().bar()中,foo()的调用是否必然发生在bar()的调用之前?这在C++标准的哪一部分有明确说明?
疑问背景:foo()调用结果的值并未被使用,且其类型在编译期即可确定,会不会被编译器优化跳过?
回答
是的,foo()的调用必然发生在bar()之前,编译器不能优化掉foo()的调用。
这一点在C++标准的多个部分有明确规定:
- 成员访问表达式的求值要求:对于类成员访问表达式
E1.E2(foo().bar()属于此类),当E2是静态成员时,E1仍会被完整求值,求值结果会被丢弃,但求值过程(包括foo()的函数调用)必须执行。以C++20标准为例,[expr.ref]/6明确指出:"If the id-expression in a member access designates a static member, the object expression is evaluated and discarded." - 求值顺序的序列关系:根据
[expr.order](表达式求值顺序)的规则,表达式中操作数的求值会被严格序列化为先完成左操作数的所有值计算和副作用,再进行后续操作。也就是说foo()的所有副作用(包括函数调用本身)必须在bar()调用之前完成。
即使foo()的返回值没有被实际使用(因为bar()是静态成员,不依赖对象实例),但语法上要求成员访问的左操作数必须是合法的对象表达式,这个表达式的求值过程是标准强制要求的,编译器不能因为返回值无用就跳过函数调用。
内容的提问来源于stack exchange,提问作者6502
相关产品推荐
相关产品推荐

