内联或不内联

时间:2011-08-01 07:33:16

标签: c++ function header member inlining

我最近写了几堂课;而且我想知道这是不好的做法,不利于性能,打破封装还是其他任何其他本质上不好的实际定义标题中的一些较小的成员函数(我确实尝试过Google!)。这是一个我有一个标题的例子,我写了很多这个:

class Scheduler {
public:
    typedef std::list<BSubsystem*> SubsystemList;

    // Make sure the pointer to entityManager is zero on init
    // so that we can check if one has been attached in Tick()
    Scheduler() : entityManager(0) { }

    // Attaches a manager to the scheduler - used by Tick()
    void AttachEntityManager( EntityManager &em )
        { entityManager = &em; }

    // Detaches the entityManager from a scheduler.
    void DetachEntityManager()
        { entityManager = 0; }

    // Adds a subsystem to the scheduler; executed on Tick()
    void AddSubsystem( BSubsystem* s )
        { subsystemList.push_back(s); }

    // Removes the subsystem of a type given
    void RemoveSubsystem( const SubsystemTypeID& );

    // Executes all subsystems
    void Tick();

    // Destroys subsystems that are in subsystemList
    virtual ~Scheduler();
private:
    // Holds a list of all subsystems
    SubsystemList subsystemList;

    // Holds the entity manager (if attached)
    EntityManager *entityManager;
};

那么,有没有像这样内联函数的错误,还是可以接受?

(另外,我不确定这是否更适合'代码审查'网站)

7 个答案:

答案 0 :(得分:11)

内联增加了耦合,并增加了类中的“噪音” 定义,使类更难阅读和理解。作为一个 一般规则,内联应被视为优化措施, 并且仅在分析器表明有必要时使用。

有一些例外:我总是内联虚拟析构函数 如果所有其他函数都是纯虚函数,则为抽象基类; 将一个单独的源文件仅用于空,这似乎很愚蠢 析构函数,如果所有其他函数都是纯虚拟的,那么 没有数据成员,析构函数不会没有变化 别的东西在改变。我偶尔会提供内联 “结构”的构造函数 - 所有数据成员的类 是公开的,没有其他功能。我也不那么严谨 关于避免在源文件中定义的类中的内联, 而不是标题 - 耦合问题显然不适用于 那种情况。

答案 1 :(得分:6)

您的所有会员功能都是单行的,所以在我看来这是可以接受的。请注意,内联函数实际上可能减少代码大小(!!),因为优化编译器会增加(非内联)函数的大小,以使它们适合块。

为了使您的代码更具可读性,我建议使用内联定义,如下所示:

class Scheduler
{
    ...

    void Scheduler::DetachEntityManager();

    ...
};


inline void Scheduler::DetachEntityManager()
{
    entityManager = 0;
}

在我看来,更具可读性。

答案 2 :(得分:2)

我认为内联(如果我理解你正确,你的意思是将简单的代码写入头文件,而不是编译器行为的习惯)有两个因素帮助提高可读性:

  1. 它将琐碎的方法与非琐碎的方法区分开来。
  2. 它使得琐碎方法的效果一目了然,是自我记录的代码。
  3. 从设计POV来看,它并不重要。在不更改subsystemList成员的情况下,您不会更改内联方法,并且在这两种情况下都需要重新编译。内联不会影响封装,因为该方法仍然是一个带有公共接口的方法。

    所以,如果这个方法是一个愚蠢的单行代码,而不需要冗长的文档或可以想象的变更需要不包含接口更改,我建议你去内联。

答案 3 :(得分:1)

它会增加可执行文件的大小,在某些情况下会导致性能下降。

请记住,内联方法要求它的源代码对于使用它的人来说是可见的(即标题中的代码)这意味着内联方法的实现中的一个小变化将导致对使用的所有内容进行重新编译定义内联方法的标题。

另一方面,这是一个小的性能提升,它对于经常调用的短方法很有用,因为它可以节省调用方法的典型开销。

如果您知道在何处使用内联方法并且不对其进行垃圾邮件,则可以使用内联方法。

编辑: 关于样式和封装,使用内联方法可以防止您使用指针实现,转发声明等等,因为您的代码位于标题中。

答案 4 :(得分:1)

内联至少有三个“缺点”:

  1. 内联函数与virtual关键字不一致(我的意思是,IMO,要么你想要一段代码代替函数调用,要么你希望函数调用是虚拟的,即多态的;无论如何,另请参阅this了解更多详细信息,了解它何时可能有意义;)

  2. 您的二进制代码会更大;

  3. 如果在类定义中包含内联方法,则会显示实现细节。

  4. 除此之外,内联方法显然是可以接受的,尽管现代编译器已经足够聪明,当它对性能有意义时,它们可以自己内联方法。所以,从某种意义上说,我认为最好将它完全留给编译器......

答案 5 :(得分:0)

class正文中的方法通常会自动inline。此外,inline是建议而不是命令。编译器通常足够聪明,可以判断是否inline函数。

您可以参考此similar question

答案 6 :(得分:0)

实际上你可以在头文件中编写所有函数,如果函数太大,编译器将自动不内联函数。只需编写您认为最适合的函数体,让编译器决定。 inline关键字也经常被忽略,如果你真的坚持使用__forceinline或类似内容(我认为这是MS特定的)内联函数。