10

我最近一直在写几节课;而且我想知道这是否是不好的做法,对性能不利,破坏封装,或者实际上在标头中定义一些较小的成员函数是否还有其他固有的坏处(我确实尝试过 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;
};

那么,像这样的内联函数真的有什么问题吗,或者可以接受吗?

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

4

7 回答 7

11

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

有一些例外:如果所有其他函数都是纯虚函数,我将始终内联抽象基类的虚析构函数;仅仅为空的析构函数提供一个单独的源文件似乎很愚蠢,如果所有其他函数都是纯虚拟的,并且没有数据成员,那么析构函数不会在没有其他东西改变的情况下发生变化。而且我偶尔会为“结构”提供内联构造函数——所有数据成员都是公共的类,并且没有其他函数。对于避免在源文件中定义的类而不是头文件中的内联,我也不太严格——耦合问题显然不适用于这种情况。

于 2011-08-01T08:17:12.507 回答
6

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

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

class Scheduler
{
    ...

    void Scheduler::DetachEntityManager();

    ...
};


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

在我看来,那更具可读性。

于 2011-08-01T07:44:26.400 回答
2

我认为内联(如果我理解正确的话,你的意思是把琐碎的代码直接写入头文件的习惯,而不是编译器的行为)通过两个因素来提高可读性:

  1. 它将平凡的方法与非平凡的方法区分开来。
  2. 它使琐碎方法的效果一目了然,成为自记录代码。

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

因此,如果该方法是一种愚蠢的单行方法,不需要冗长的文档或可能需要不包含接口更改的更改,我建议使用内联。

于 2011-08-01T07:46:06.633 回答
1

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

请记住,内联方法要求其源代码对任何使用它的人都是可见的(即标头中的代码),这意味着内联方法的实现中的微小更改将导致对使用标头的所有内容进行重新编译定义了内联方法。

另一方面,这是一个小的性能提升,它适用于真正频繁调用的短方法,因为它可以节省调用方法的典型开销。

如果您知道在哪里使用它们并且不向它们发送垃圾邮件,则内联方法很好。

编辑:关于样式和封装,使用内联方法可以防止您使用诸如指向实现的指针、前向声明等内容。因为您的代码位于标头中。

于 2011-08-01T07:37:28.610 回答
1

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

  1. 内联函数与 virtual 关键字不一致(我的意思是概念上,IMO,要么你想要一段代码来代替函数调用,要么你希望函数调用是虚拟的,即多态的;无论如何,另参见更多关于何时实际可行的详细信息);

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

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

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

于 2011-08-01T07:39:48.430 回答
0

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

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

于 2011-08-01T07:41:33.237 回答
0

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

于 2011-08-01T08:19:56.557 回答