内联或不内联

To inline or not to inline

本文关键字:      更新时间:2023-10-16

我最近一直在写一些类;我想知道它是否不好的做法,坏的性能,打破封装或是否有任何其他固有的坏实际上定义一些较小的成员函数在头(我确实尝试谷歌!)。这里有一个例子,我写了很多这样的标题:

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;
};
那么,像这样的内联函数是否真的有什么错误的,或者它是可以接受的?

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

内联增加了耦合,并增加了类中的"噪声"定义,使类更难阅读和理解。作为一个一般来说,内联应被视为一种优化措施,只有侧写师说有必要时才会使用。

的虚析构函数总是内联的如果所有其他函数都是纯虚函数,则为抽象基类;有一个单独的源文件,只是为了一个空的,这似乎很愚蠢如果所有其他函数都是纯虚函数,则使用没有数据成员,析构函数不会改变别的东西在变化。我偶尔会提供内联"结构"类的构造函数,其中所有数据成员都是公共的,并且没有其他函数。我也不那么严谨了关于在源文件中定义的类中避免内联,而不是标头—耦合问题显然不适用这种情况下。

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

为了使你的代码更易读,我建议使用内联定义,如下所示:

class Scheduler
{
    ...
    void Scheduler::DetachEntityManager();
    ...
};

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

在我看来这更容易读懂。

我认为内联(如果我没理解错的话,你的意思是把琐碎的代码直接写进头文件的习惯,而不是编译器的行为)从两个方面提高了可读性:

  1. 区分重要的方法和不重要的方法。
  2. 它使琐碎方法的效果一目了然,成为自文档代码。

从设计角度来看,这并不重要。在不更改subsystemList成员的情况下,您不会更改内联方法,在这两种情况下都需要重新编译。内联不影响封装,因为方法仍然是一个具有公共接口的方法。

因此,如果方法是一个愚蠢的一行代码,不需要冗长的文档,或者不包含接口更改的可想象的更改需求,我建议使用内联。

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

请记住,内联方法要求它的源代码对使用它的人是可见的。在头文件中的代码),这意味着在你的内联方法的实现中的一个小的改变将导致重新编译所有使用了定义了内联方法的头文件。

另一方面,这是一个很小的性能提升,对于频繁调用的短方法很好,因为它将节省调用方法的典型开销。

内联方法是好的,如果你知道在哪里使用它们,不垃圾。

编辑:关于样式和封装,使用内联方法可以防止使用指针指向实现、前向声明等。因为你的代码在头文件中。

内联至少有三个"缺点":

  1. 内联函数与虚拟关键字不一致(我的意思是在概念上,IMO,要么你想要一段代码来代替函数调用,要么你想要函数调用是虚拟的,即多态;无论如何,也请参阅此以了解更多关于何时可以实际意义的细节);

  2. 你的二进制码会变大;

  3. 如果你在类定义中包含了内联方法,你就暴露了实现细节。

除此之外,内联方法显然没问题,尽管现代编译器已经足够聪明,当它对性能有意义时,可以自己内联方法。所以,在某种意义上,我认为最好把它留给编译器。

class主体内的方法通常是自动inline的。此外,inline是一个建议,而不是一个命令。编译器通常足够聪明,可以判断是否inline函数。

你可以参考这个类似的问题

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

相关文章:
  • 没有找到相关文章