C:对琐碎的package方法进行的优化

C++: Optimizations made on wrapped methods that are trivial

当我编写package器类时,许多方法都采用以下形式:

1
2
3
4
5
6
7
8
class Wrapper{
    public:
        vec3 getPos(){          return m_position.get();  }
        void setPos(vec3 pos){  m_position.set(pos);      }
    private:
        ThingGettingWrapped m_position;
    }
}

但是我很好奇,getPos()setPos()是否会产生开销,还是现代编译器足够聪明以优化委托,所以wrapper.set/get()等同于wrapper.m_thingWrapped.set/get()

(我知道示例中已内联方法,但假定未显式内联和单独定义方法)


优化器可以扩展内联调用,在这种情况下,额外的调用没有任何开销。

如果未内联扩展调用,则类似的package器可能会产生开销。

现代编译器的优化器进行内联扩展。

assume they are not explicitly inlined and defined separately

除非优化程序可以内联扩展调用,否则开销(很小)。您可以通过在与定义该函数相同的转换单元中调用该函数来保证内联的能力。像在示例中所做的那样,内联函数的定义对所有翻译单元都启用并实施了此功能,因为内联函数均在所有翻译单元中定义。允许跨翻译单元进行内联扩展的另一种方法是LTO。

一个函数不需要是内联的,以便它可以内联扩展,并且不需要优化器来内联扩展所有对内联函数的调用。内联函数将始终是可扩展内联的。不是内联的函数在某些情况下可以扩展,但并非总是可以扩展。


只要遵循一些简单规则,编译器就会内联这些函数:

  • 它们不是虚拟的(在您的情况下不是,但是可能在其他位置)-编译器通常无法内嵌虚拟函数-因为这会使虚拟函数的整个概念变得无用。
  • 该函数的实际实现在编译源调用getPos的过程中可供编译器使用。同样,不可能编译示例代码,但是您可以将getPossetPos声明为成员函数,而无需在类中提供它们的主体,在这种情况下,编译器将(不必)能够内联他们。 [1]
  • [1]支持链接时间优化(LTO)或整个程序优化的编译器,某些编译器供应商喜欢调用它,即使源不可用也可以内联函数-这是因为直到完成最终代码生成为止之后,将源文件的半编译版本存储在目标文件中。以我的经验,LTO并不用于大多数项目。