如何不指定函数参数的精确评估顺序有助于C&C++编译器生成优化代码?

Des*_*tor 3 c++ optimization operator-precedence compiler-optimization unspecified-behavior

#include <iostream>
int foo() {
    std::cout<<"foo() is called\n";
    return 9;
}
int bar() {
    std::cout<<"bar() is called\n";
    return 18;
}
int main() {
    std::cout<<foo()<<' '<<bar()<<' '<<'\n';
}
// Above program's behaviour is unspecified
// clang++ evaluates function arguments from left to right: http://melpon.org/wandbox/permlink/STnvMm1YVrrSRSsB
// g++ & MSVC++ evaluates function arguments from right to left
// so either foo() or bar() can be called first depending upon compiler.
Run Code Online (Sandbox Code Playgroud)

上述程序的输出取决于编译器.未指定评估函数参数的顺序.我读到这个的原因是它可以导致高度优化的代码.如何不指定函数参数的精确评估顺序有助于编译器生成优化代码

AFAIK,评估顺序严格按Java,C#,D等语言规定.

Mar*_*ork 9

我认为这个问题的整个前提是错误的:

如何不指定函数参数的精确评估顺序有助于C&C++编译器生成优化代码?

它不是关于优化代码(尽管它确实允许).它不会惩罚编译器,因为底层硬件具有某些ABI约束.

一些系统依赖于按相反顺序推送堆叠的参数,而其他系统依赖于正向顺序.C++可以在各种约束下运行.如果您在语言级别强制执行订单,则需要一些系统支付罚款才能执行该订单.

C++的第一条规则是"如果你不使用它,那你就不应该付钱".因此,强制执行命令将违反C++的主要指令.


M.M*_*M.M 7

它没有.至少,今天没有.也许它过去做过.

提议为C++ 17表明定义函数调用,左右计算顺序operator<<等.

如该文章的第7节所述,该提议通过编译Windows NT内核进行了测试,实际上它导致了某些基准测试的速度提升.作者的评论:

值得注意的是,这些结果是针对最糟糕的情况,即优化器尚未更新以了解并利用新的评估规则,并且盲目地迫使它们从左到右评估函数调用.

表明还有进一步改善速度的空间.


Ser*_*eyA 5

评估顺序与参数传递方式有关.如果使用stack来传递参数,则从右到左进行评估有助于提高性能,因为这是参数被推入堆栈的方式.

例如,使用以下代码:

void foo(bar(), baz());
Run Code Online (Sandbox Code Playgroud)

假设调用convention是'通过堆栈传递参数',C调用约定要求从最后一个开始将参数推入堆栈 - 这样当被调用函数读取它时,它将首先弹出第一个参数并且能够支持可变参数函数.如果评估顺序是从左到右,则结果bar()必须保存在临时,而不是baz()被调用,它的结果被推送,然后是临时推送.但是,从右到左的评估允许编译器避免临时.

如果参数通过寄存器传递,则评估顺序并不过分重要.

  • @Destructor它不是严格便携的.如果使用未指定或未定义的行为,则无法保证该行为.至少未指定,您可以检查实现,但为什么要使用. (2认同)
  • @Destructor:代码不可移植,取决于评估顺序.如果您希望编写错误的函数依赖于全局状态并希望强制执行订单,则首先在单独的语句中对其进行评估(分配给引用). (2认同)
  • 代码可移植性没有任何变化,因为评估顺序未指定.如果指定它,代码可移植性将受到影响,因为固定的参数passiing可能会损害性能.编写未定义的代码并且即使在相同的编译器上也是不可移植的. (2认同)
  • @Destructor,您可以自由使用这些语言.他们不关心低级别的表现. (2认同)