Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 编译器是否允许在不同的函数参数中交错计算子表达式?_C++ - Fatal编程技术网

C++ 编译器是否允许在不同的函数参数中交错计算子表达式?

C++ 编译器是否允许在不同的函数参数中交错计算子表达式?,c++,C++,我想知道以下情况: 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; retur

我想知道以下情况:

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()));
在GCC5.4.0上运行此测试会让我的想法更符合逻辑

func y
func b
func x
func a

但这当然没有告诉我标准要求什么。如果能获得对该标准的引用,那就太好了。

在C++14及更早版本中,
x->y->a->b
是可能的。这里的顺序关系是:

  • x
    的调用在调用
    a
    之前排序
  • y
    的调用在调用
    b
    之前排序
  • a
    的调用在调用
    f
    之前排序
  • b
    的调用在调用
    f
    之前排序
订单上没有其他限制。如果要强制执行某些特定的顺序,则必须将此调用分解为多个完整表达式

在C++14标准中,注释[expr.call]/8澄清了这一意图:

[注意:后缀表达式和参数的求值都是相对不排序的。参数求值的所有副作用都是在函数输入之前排序的。-结束注意]


如注释中所述,列出了更多标记为“自C++17”的排序规则。这是基于C++17最新发布的草稿。因此,对于C++17,这种顺序可能不再被允许。

另一种看待它的方式:

在开始评估a或b之前,评估x和y没有任何好处。事实上,会有处罚。额外的中间结果必须临时保存在某个地方,这可能需要额外的堆栈推送/弹出,或者消耗额外的CPU寄存器(过度使用会导致额外的堆栈操作)。虽然对于您提供的示例可能影响不大或没有影响,但更复杂的案例将揭示效率低下的原因


该规则可被视为最懒惰的评估,即在需要之前不执行评估,以避免产生额外的临时结果。

我继续,为您的问题提供了更具描述性的标题。如果您对此有任何问题,请随意更改。感谢chris和panta rei的帮助编辑。函数参数的计算与函数的计算无关。关于“作为一个单元进行评估”的部分仅指函数的评估-对
a(…)
b(…)
的评估不会交错。+1这就是为什么我们使用
make_unique(args)
而不是
new T(args)
;在后一种情况下,
func(unique_ptr(new T(args)),new unique_ptr(new U(args)))
可能会泄漏。@GManNickG很好的一点,我没有考虑过从这个角度使_变得唯一。您可以从链接的“对A和B的评估是不确定顺序的:它们可以按任何顺序执行,但不能重叠:在函数调用中,A将在B之前完成,或者B将在A.[…]15)之前完成,每个参数初始化的值计算和副作用相对于任何其他参数的值计算和副作用是不确定的。”。这似乎表明
a(x())
b(y())
不能重叠。@dxiv在那种情况下我相信”参数“仅指评估参数表达式的最终结果;这里的“原子”单位是该结果和参数之间的转换,该参数可能与参数具有不同的类型,因此涉及转换序列。cppreference所基于的当前C++17措辞是
5.2.2[expr.call]p5
当然——这有一些好处:大多数编程语言都定义了这类表达式的求值顺序,这意味着更少的惊喜(对于新的程序员和有经验的程序员来说),以及更少的由于求值顺序不同于程序员预期而导致的错误。此外,实践中是否有任何证据支持关于效率低下的说法也值得怀疑,第7节结论特别是我应该认为表达式评估的顺序只会影响副作用,而副作用是“最佳实践”应该避免的,所以无论执行的顺序如何,没有人会感到意外。@M.M事实上,如果你从一个冗长的帖子中看到这个({})帖子,你会看到附件中有一个建议,要求严格按照从左到右的顺序进行评估。
func y
func b
func x
func a