如果我们有三个这样组成的函数(foo,bar和baz)...
foo(bar(), baz())
C ++标准是否可以保证在baz之前对bar进行评估?
Answers:
不,没有这样的保证。根据C ++标准未指定。
Bjarne Stroustrup还在“ The C ++ Programming Language”第三版第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]表达式中的内容:
除非另有说明[例如特殊规则
&&
和||
],个体经营者和单个表达式的子表达式,并且其中的副作用发生的顺序的操作数的计算顺序,是不确定的。
所以即使你在问是否bar()
将之前运行baz()
的foo(bar() + baz())
,订单仍然是不确定的。
&
,&&
保证从左到右的求值:如果第一个操作数为,则不求第二个操作数false
。”
在C ++ 11中,相关文本可以在8.3.6默认参数/ 9(强调我的)中找到。
每次调用函数时都会评估默认参数。函数参数的求值顺序不确定。因此,即使未对函数的参数进行求值,也不得在默认参数中使用该函数的参数。
C ++ 14标准也使用相同的语言,可在同一部分中找到。
正如其他人已经指出的那样,该标准并未对此特定方案的评估顺序提供任何指导。然后,将评估的顺序留给编译器,并且编译器可能会有保证。
重要的是要记住,C ++标准实际上是一种指示编译器构造汇编/机器代码的语言。标准只是方程式的一部分。如果该标准含糊不清或专门为实现定义,则应转向编译器并了解其如何将C ++指令转换为真正的机器语言。
因此,如果评估顺序是必需的,或者至少是重要的,并且不要求与交叉编译器兼容,请研究编译器最终如何将它们组合在一起,您的答案可能最终就在那。请注意,编译器将来可能会更改其方法