代码之家  ›  专栏  ›  技术社区  ›  Marcin

C++编译器会优化未使用的返回值吗?

  •  4
  • Marcin  · 技术社区  · 16 年前

    如果我有一个返回对象的函数,但调用方从未使用这个返回值,编译器会优化掉副本吗?(可能是始终/有时/从不回答。)

    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 对象被复制了吗?它甚至可以建造吗?(我知道这可能取决于编译器,但让我们将讨论范围缩小到流行的现代版本。)

    编辑:让我们简化一下,因为在一般情况下似乎没有共识。如果…怎么办 返回值 是一个int,我们返回0而不是 successfulResultObject ?

    6 回复  |  直到 13 年前
        1
  •  3
  •   Martin v. Löwis    16 年前

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

    如果复制构造函数是内联的,则编译器可能能够内联调用,这反过来可能会导致删除其大部分代码(还取决于更改成员和从不失败的函数是否是内联的)。

        2
  •  1
  •   kasperjj    16 年前

        3
  •  1
  •   Sniggerfardimungus    16 年前

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

    如果你有一个很好的理由关注CPU调用的方法调用(过早优化是所有邪恶的根源),你可能会考虑到许多可用的内联选项,包括(GASP!)宏。

    您真的需要在这个级别进行优化吗?

        4
  •  1
  •   SoapBox    16 年前

    如果返回值为int,并且返回0(如编辑的问题中所示),则 也许 走开。

    您必须查看底层程序集。如果函数未内联,则底层程序集将执行mov eax,0(或xor eax,eax)以将eax(通常用于整数返回值)设置为0。如果函数是内联的,这肯定会得到优化。

    但是,如果您担心返回大于32位的对象时会发生什么,那么这个senario就没有太大用处。您需要参考unedit问题的答案,这描绘了一幅非常好的画面:如果所有内容都是内联的,那么大部分内容都将被优化。如果它不是内联的,那么即使函数实际上没有做任何事情,也必须调用函数,这包括对象的构造函数(因为编译器不知道构造函数是修改了全局变量还是做了其他奇怪的事情)。

        5
  •  0
  •   Paul Tomblin    16 年前

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

        6
  •  0
  •   dmckee --- ex-moderator kitten    16 年前

    窥视孔优化器很有可能捕捉到这一点。许多(大多数?)编译器都实现了一个,因此答案可能是“是”。

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


        7
  •  0
  •   Gukki5    4 年前

    mov 未使用返回值时,不会生成。

    https://gcc.godbolt.org/z/v5WGPr

    enter image description here