为什么在c ++中未指定函数参数的评估顺序?

时间:2012-09-22 03:25:12

标签: c++ operator-precedence

标准未指定使用此行评估参数的顺序:

  

参数的评估顺序未指定。

什么是

  

在没有限制的情况下可以生成更好的代码   表达评估顺序

暗示?

要求所有编译器评估函数参数Left to Right有什么缺点?由于这个未指定的规范,编译器执行了哪些优化?

2 个答案:

答案 0 :(得分:26)

允许编译器重新排序操作数的评估,为优化增加了更多空间。

这是一个完整的例子,用于说明目的。

假设处理器可以:

  • 每个周期发出1条指令。
  • 在1个周期内执行添加。
  • 在3个周期内执行乘法。
  • 可以同时执行加法和乘法。

现在假设您有一个函数调用,如下所示:

foo(a += 1, b += 2, c += 3, d *= 10);

如果您要在没有OOE的处理器上从左到右执行此操作:

Cycle - Operation
0     -    a += 1
1     -    b += 2
2     -    c += 3
3     -    d *= 10
4     -    d *= 10
5     -    d *= 10

现在,如果您允许编译器对它们进行重新排序:(并首先开始乘法)

Cycle - Operation
0     -    d *= 10
1     -    a += 1, d *= 10
2     -    b += 2, d *= 10
3     -    c += 3

所以6个周期对4个周期。

这再次完全是人为的。现代处理器比这复杂得多。但是你明白了。

答案 1 :(得分:2)

这是一个简单的例子。假设您有一个函数调用,如下所示:

// assume that p is a pointer to an integer
foo(*p * 3, bar(), *p * 3 + 1);

编译器需要解除引用p两次(并根据结果进行一些计算)并调用bar一次。如果编译器很聪明,它可能会将评估重新排序为

int temp = *p * 3;
foo(temp, bar(), temp + 1);

这样它只需要进行一次“取消引用,乘以3”。这被称为常见的子表达式消除。