C++ C++;:对简单的包装方法进行的优化

C++ C++;:对简单的包装方法进行的优化,c++,optimization,wrapper,C++,Optimization,Wrapper,在编写包装器类时,许多方法采用以下形式: class Wrapper{ public: vec3 getPos(){ return m_position.get(); } void setPos(vec3 pos){ m_position.set(pos); } private: ThingGettingWrapped m_position; } } 然而,我很好奇,getPos()和set

在编写包装器类时,许多方法采用以下形式:

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\u thingWrapped.set/get()


(我知道在我的示例中这些方法是内联的,但假设它们没有显式内联并单独定义)

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

  • 它们不是虚拟的(在您的例子中不是,但可能在其他地方)-编译器通常不能内联虚拟函数-因为这会使虚拟函数的整个概念变得无用
  • 编译器在编译源代码调用
    getPos
    期间可以使用该函数的实际实现。同样,编译示例代码是不可能的,但是可以将
    getPos
    setPos
    声明为成员函数,而不在类中给它们一个主体,在这种情况下,编译器将(不一定)能够内联它们。[1]
  • [1] 支持链接时间优化(LTO)或某些编译器供应商喜欢称之为全程序优化的编译器可以使用内联函数,即使源代码不可用——这是因为最终代码生成要等到以后才能完成,因此源代码的半编译版本存储在目标文件中。根据我的经验,大多数项目都不使用LTO。

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

    如果调用不是内联扩展的,这样的包装器可能会产生开销

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

    假设它们没有显式内联并单独定义

    除非优化器可以内联扩展调用,否则将有(小)开销。您可以通过在定义函数的同一翻译单元中调用该函数来保证内联的能力。定义内联函数-就像您在示例中所做的那样-为所有转换单元启用并强制执行此功能,因为内联函数都是在所有转换单元中定义的。允许跨翻译单元进行内联扩展的另一种方法是


    函数不需要内联才能内联扩展,也不需要优化器内联扩展对内联函数的所有调用。内联函数始终是可内联扩展的。非内联函数在某些情况下可能是可扩展的,但并非总是如此。

    包装器非常常见。任何未能优化掉您所询问的开销的优化器都很难被称为“优化器”。除非我误解了“单独定义”的含义:如果优化器看不到定义是一个微不足道的包装器,它就无法对其进行优化。“显式内联”并不重要。如果优化器可以看到定义,它可以内联函数。1。下载一个现代编译器。2.你自己看看吧。3.没有第三步,我不同意第二步。gcc和msvc++将内联它们,即使它们存在于单独的文件中。仅使用LTO,根据我的经验,LTO没有尽可能多地使用。
    -funit-at-a-time
    在gcc中,当与多个文件一起使用时,优化器可以在优化时从所有翻译单元获取信息。如果所有单元(定义函数的单元和使用函数的单元)都同时编译,那么即使没有LTO,也不允许跨转换单元进行内联扩展吗?还是我弄错了?在gcc的现代版本中,
    -funit-at-a-time
    似乎什么都不做?@matstpeterson啊,显然这个选项现在什么都不做。但也许它所产生的效果现在总是被启用了?