初始化程序列表vs构造函数分配vs变量定义

时间:2018-07-05 03:51:42

标签: c++ class constructor initialization initializer-list

我试图了解以下两类之间的真正区别。

class A
{
public:
    A()
    :width(500)
    ,height(300){};
    int width;
    int height;
};

class B
{
public:
    B()
    {
        width = 500;
        height = 300;
    };
    int width;
    int height;
};

class C
{
public:
    int width = 500;
    int height = 300;
};

您认为哪种方法是初始化类中的widthheight变量的最佳方法?

我应该坚持一种方法吗?

1 个答案:

答案 0 :(得分:1)

此摘录摘自Stanley B. Lippman的“ Inside the C ++ Object Model”。

  

在以下情况下,您必须使用成员初始化列表:   程序编译的顺序:
  1.初始化参考成员时
  2.初始化const成员时
  3.在调用带有一组参数的基类或成员类构造函数时
  4.一些效率案例。 (这里程序是正确的,没有成员初始化列表)

对于1-3点,成员初始化列表是必须的。
对于第4点,它不是强制性的。

例如(点4),给定:

class Word {
   String _name;
   int _cnt;
   public:
   // not wrong, just naive ...
   Word() {
      _name = 0;
      _cnt = 0;
   }
};

Word构造函数的实现将_name初始化一次,然后使用赋值覆盖初始化,从而导致临时String对象的创建和销毁。

本来可以编码出效率更高的实现方式:

// preferred implementation
Word::Word : _name( 0 )
{
    _cnt = 0;
}

由于这种优化,许多人更喜欢成员初始化列表,这是编写构造函数的默认方法。

// some insist on this coding style
Word::Word()
   : _cnt( 0 ), _name( 0 )
   {}

此时要问的一个合理问题是,成员初始化列表实际发生了什么

编译器遍历初始化列表,在任何显式用户代码之前按正确的顺序在构造函数中插入初始化。
例如,先前的Word构造函数扩展如下:

// Pseudo C++ Code
Word::Word( /* this pointer goes here */ )
{
   _name.String::String( 0 );
   _cnt = 0;
}
  

注意:确定列表条目的排列顺序   根据类声明中成员的声明顺序,   而不是初始化列表中的顺序。在这种情况下,_name是   在_cnt中的Word之前声明,因此放在第一位。

所以回到您的问题:

class B很好(因为您使用的是原始数据类型)。

class A将生成与class B相同的代码

对于class C,首先调用默认构造函数,然后将初始化widthheight
当要使用多个构造函数时,应该首选此方法,并且对于每个构造函数widthheight必须默认为所需的值。

但是,由于C ++ 11的问世以及使用{}作为统一初始化,因此,编写class C的更推荐方法是:

class C
{
    public:
    int width {500};
    int height {300};
};