【发布时间】:2011-02-25 11:13:38
【问题描述】:
如果我们有三个这样组成的函数(foo、bar 和 baz)......
foo(bar(), baz())
C++ 标准是否保证 bar 将在 baz 之前被评估?
【问题讨论】:
如果我们有三个这样组成的函数(foo、bar 和 baz)......
foo(bar(), baz())
C++ 标准是否保证 bar 将在 baz 之前被评估?
【问题讨论】:
不,没有这样的保证。根据 C++ 标准,它是未指定的。
Bjarne Stroustrup 也在“C++ 编程语言”第 3 版第 6.2.2 节中明确表示,并有一些推理:
更好的代码可以在 没有表达限制 评价顺序
虽然从技术上讲,这指的是同一节的前面部分,它说表达式部分的评估顺序也是未指定的,即
int x = f(2) + g(3); // unspecified whether f() or g() is called first
【讨论】:
来自[5.2.2]函数调用,
参数的评估顺序未指定。参数表达式求值的所有副作用在输入函数之前生效。
因此,不能保证bar()会在baz()之前运行,只有bar()和baz()会在foo之前被调用。
另请注意 [5] 表达式:
除非另有说明 [例如
&&和||] 的特殊规则、单个运算符的操作数和单个表达式的子表达式的求值顺序以及副作用发生的顺序是未指定的。
因此,即使您在foo(bar() + baz()) 中询问bar() 是否会在baz() 之前运行,顺序仍然未指定。
【讨论】:
& 不同,&& 保证从左到右的评估:如果第一个操作数不评估第二个操作数操作数是false。”
没有指定 bar() 和 baz() 的顺序 - 标准中唯一说的是它们都将在 foo() 被调用之前进行评估。来自 C++ 标准,第 5.2.2/8 节:
参数的评估顺序 未指定。
【讨论】:
bar的第1行,然后baz的第1行,然后bar的第2行,等等.),这也很好。 :-)
C++17 为在 C++17 之前未指定的运算符指定求值顺序。看问题What are the evaluation order guarantees introduced by C++17? 但是注意你的表情
foo(bar(), baz())
仍有未指定的评估顺序。
【讨论】:
在C++11中,相关的文字可以在8.3.6 Default arguments/9找到(重点是我的)
每次调用函数时都会评估默认参数。 函数参数的求值顺序未指定。因此,函数的参数不应在默认参数中使用,即使它们没有被评估。
C++14 标准也使用相同的措辞,可在the same section 下找到。
【讨论】:
正如其他人已经指出的那样,该标准并未就此特定场景的评估顺序提供任何指导。这个评估顺序然后留给编译器,编译器可能有保证。
请务必记住,C++ 标准实际上是一种指导编译器构建汇编/机器代码的语言。标准只是方程式的一部分。如果标准模棱两可或具体实现定义,您应该求助于编译器并了解它如何将 C++ 指令翻译成真正的机器语言。
因此,如果求值顺序是一项要求,或者至少很重要,并且不需要与交叉编译器兼容,那么请研究一下您的编译器最终将如何将这些组合在一起,您的答案最终可能就在那儿。请注意,编译器将来可能会更改其方法
【讨论】: