会用c++编译器优化远未使用返回的价值?
-
07-07-2019 - |
题
如果我有一个函数,返回的一个目的,但这返回值是从来没有使用的来电,将编译器化务的副本?(可能是一个总是/有时/永远不会回答。)
基本的例子:
ReturnValue MyClass::FunctionThatAltersMembersAndNeverFails()
{
//Do stuff to members of MyClass that never fails
return successfulResultObject;
}
void MyClass::DoWork()
{
// Do some stuff
FunctionThatAltersMembersAndNeverFails();
// Do more stuff
}
在这种情况下,会的 ReturnValue
目得到复制吗?它甚至获得建造?(我知道这可能取决于编译器,但我们缩小这一讨论下流行的现代化。)
编辑:让我们简化了这一点,因为似乎没有达成共识,在一般的情况。如果有什么 ReturnValue
是一个int,并且我们回0,而不是的 successfulResultObject
?
解决方案
如果ReturnValue类有一个非平凡的复制构造函数,编译器不能删除对复制构造函数的调用 - 它是由调用它的语言强制执行的。
如果复制构造函数是内联的,则编译器可能能够内联调用,这反过来可能会导致消除大部分代码(也取决于FunctionThatAltersMembersAndNeverFails是否为内联函数)。
其他提示
他们最有可能将如果优化水平会导致它们的内联的代码。如果不,他们会产生两种不同的译文同样的代码,使它的工作,这可能打开多边情况下的问题。
链接器可以处理这类事情,即使原始调用者和被调用者位于不同的编译单元中。
如果您有充分的理由担心专用于方法调用的CPU负载(过早优化是万恶之源),您可以考虑使用许多内联选项,包括(喘气!)一个宏
你真的需要在这个级别进行优化吗?
如果返回值为int并且您返回0(如编辑后的问题中所示),则此可能会被优化掉。
您必须查看基础程序集。如果函数没有内联,那么底层程序集将执行mov eax,0(或xor eax,eax)将eax(通常用于整数返回值)设置为0.如果函数内联,这肯定会得到优化了。
但如果您担心返回大于32位的对象时会发生什么,那么这个Senario并不太有用。你需要参考未来问题的答案,这些问题描绘了一幅非常好的图片:如果所有内容都被内联,那么大部分都会被优化掉。如果它没有内联,则必须调用函数,即使它们没有真正做任何事情,并且包括对象的构造函数(因为编译器不知道构造函数是修改了全局变量还是做了别的奇怪的事情)
我怀疑大多数编译器是否可以在不同的编译对象(即不同的文件)中执行此操作。也许如果他们都在同一个文件中,他们可以。
窥视孔优化器很有可能会抓住这个。许多(大多数?)编译器实现了一个,所以答案可能是“是”。
正如其他人所指出的那样,这在AST改写水平上并不是一个微不足道的问题。
窥孔优化器在与汇编语言等效的级别(但在生成实际机器代码之前)处理代码表示。有可能注意到返回值加载到寄存器中,然后是没有中间读取的覆盖,只需删除负载即可。这是根据具体情况完成的。