初始化类成员的最佳方式

Best way to initialize class members?

本文关键字:最佳 方式 成员 初始化      更新时间:2023-10-16

使用c++11标准,我可以用两种方式初始化类成员:

class MyClass
{
private: 
    int a = 5;
};

class MyClass
{
private: 
    int a;
public:
    MyClass()
    {
        a = 5;
    }
};

是否有一种方法因为某种原因优于另一种方法,或者它更像是一种个人风格的选择?

第二个例子是而不是初始化。

因此,在这两个例子中,第一个是初始化类成员的最佳方式。

传统的初始化方式如下:

class MyClass
{
private: 
    int a;
public:
    MyClass()
      : a(5)
    {}
};

标准c++基金会的这一页建议,在其他条件相同的情况下,您应该更倾向于使用初始化列表。即:

喜欢

class Foo {
  public:
     Foo(int bar) : m_bar(bar) { }
  private:
    int m_bar;
};

/

class Foo {
  public:
    Foo(int bar) {
      m_bar = bar;
    }
  private:
    int m_bar;
};

他们的理由是:

考虑下面初始化成员对象x_的构造函数使用初始化列表:Fred::Fred() : x_(whatever) { }。的这样做最常见的好处是提高了性能。为例如,如果表达式whatever与成员类型相同变量x_,则构造whatever表达式的结果直接在x_中—编译器不会单独复制对象。即使类型不相同,编译器通常也是使用初始化列表比使用作业。

另一种(低效的)构建构造函数的方法是通过赋值,例如:Fred::Fred() { x_ = whatever; }。在这种情况下,表达式无论什么原因导致一个单独的临时对象被创建,这将临时对象传递给x_对象的赋值操作符。然后该临时对象在;处被析构。这是低效的。

如果这还不够糟糕的话,还有另一个低效率的来源在构造函数中使用赋值时:成员对象将得到由其默认构造函数完全构造,这可能是for例如,分配一些默认的内存量或打开一些默认的文件。所有这些工作都可能付诸东流,如果这种表达赋值操作符导致对象关闭该文件和/或释放内存(例如,如果默认构造函数没有分配)内存池足够大或者打开了错误的文件)。

结论:在其他条件相同的情况下,如果使用初始化列表而不是赋值。

关于默认初始化(如Foo(): m_bar(5) { }),我也会使用初始化器列表方法(或c++ 11成员初始化方法),只是为了与上述指南保持一致。