2008-11-07 56 views
4

如果我有一个函数返回一个对象,但这个返回值从来不被调用者使用,编译器是否会优化拷贝? (可能是经常/有时/从不回答。)C++编译器会优化未使用的返回值吗?

小学例如:

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

回答

3

如果ReturnValue类有一个非平凡的拷贝构造函数,编译器不能消除对拷贝构造函数的调用 - 它被调用的语言强制执行。

如果复制构造函数是内联的,编译器可能能够内联调用,这反过来可能会导致它的大部分代码被删除(也取决于FunctionThatAltersMembersAndNeverFails是否内联)。

0

我怀疑大多数编译器可以做到这一点,如果他们在不同的编译对象(即不同的文件)。也许如果他们都在同一个文件中,他们可以。

+0

同意。只要返回值从未用于任何调用,启用“整个程序优化”也可以使其发生。 – 2008-11-07 18:07:54

+0

@Drew,是“整个程序优化”的vC++的东西,因为我无法想象它可能在Linux/Unix环境中。 – 2008-11-07 18:13:09

+0

对此的努力的传言,例如:http://www.airs.com/blog/archives/100 – 2008-11-08 12:09:25

1

如果优化级别导致它们内联代码,它们很可能会出现。如果没有,他们将不得不生成两个不同的相同代码的翻译,以使其工作,这可能会导致很多边缘案例问题。

1

即使原始调用者和调用者在不同的编译单元中,链接器也可以处理这类事情。

如果您有充分的理由关注专用于方法调用的CPU负载(过早优化是所有恶意的根源),您可以考虑使用多种内联选项,包括(gasp!)a宏。

您是否真的需要在此级别进行优化?

0

窥视孔优化器有一个很好的机会可以解决这个问题。许多(大多数?)编译器实现了一个,所以答案可能是“是”。

正如其他人所指出的,这在AST重写级别上并不是一个微不足道的问题。


窥孔优化器在与汇编语言(但在生成实际机器代码之前)相同的级别上表示代码。有机会注意到返回值加载到一个寄存器,然后覆盖没有中间读取,并删除负载。这是在个案基础上完成的。

1

如果返回值是一个int并且返回0(如在编辑的问题中),那么这个可能会被优化掉。您必须查看底层组件。如果函数未内联,则底层程序集将执行mov eax,0(或xor eax,eax)将eax(通常用于整数返回值)设置为0.如果函数内联,则肯定会得到优化了。

但是,如果您担心返回大于32位的对象时会发生什么,则此senario不太有用。你需要参考unnedit问题的答案,这个问题描绘了一幅相当不错的图片:如果一切都内联,那么大部分内容都会被优化。如果它没有被内联,那么函数必须被调用,即使它们没有做任何事情,也包括对象的构造函数(因为编译器不知道构造函数是修改全局变量还是做了其他奇怪的事情) 。