我想知道以下情况:
void f(int a, int b) { }
int a(int x) { std::cout << "func a" << std::endl; return 1; }
int b(int x) { std::cout << "func b" << std::endl; return 2; }
int x() { std::cout << "func x" << std::endl; return 3; }
int y() { std::cout << "func y" << std::endl; return 4; }
f(a(x()), b(y()));
阅读http://en.cppreference.com/w/cpp/language/eval_order后,我仍然难以理解以下评估顺序是否可行:
x()
- &gt; y()
- &gt; a()
- &gt; b()
或标准保证a(x())
和b(y())
将被评估为单位,可以这么说。
换句话说,是否有可能打印
func x
func y
func a
func b
在GCC 5.4.0上运行此测试让我觉得更合乎逻辑
func y
func b
func x
func a
但这当然没有告诉我标准要求的内容。获得对标准的引用会很好。
答案 0 :(得分:14)
在C ++ 14及更早版本中,x -> y -> a -> b
是可能的。这里的排序关系是:
x
之前,对a
的来电已排序。y
之前,对b
的来电已排序。a
之前,对f
的来电已排序。b
之前,对f
的来电已排序。订单没有其他限制。如果你想强制执行某些特定的排序,那么你必须将这个调用分解为多个完整表达式。
在C ++ 14标准中,注意事项[expr.call] / 8澄清了这一意图:
[注意:后缀表达式和参数的评估都是相对于彼此无法排序的。在输入函数之前,对参数评估的所有副作用进行排序。 - 结束记录]
如评论中所述,cppreference page列出了更多标记为“自C ++ 17以来”的排序规则。这是基于n4606,最新发布的C ++ 17草案。因此,对于C ++ 17,可能不再允许这个顺序。
答案 1 :(得分:2)
另一种看待它的方式:
在开始评估a或b之前,评估x和y都没有任何好处。事实上,会有一个惩罚。额外的中间结果必须暂时保存在需要额外堆栈推送/弹出的地方,或者消耗额外的CPU寄存器(过度使用会导致额外的堆栈操作)。虽然对于您提供的示例可能影响很小或没有影响,但更复杂的案例会显示效率低下。
该规则可被视为最可能的评估,即在需要之前不进行评估,以避免携带额外的临时结果。