初始化列表的好处

我所知道的使用初始化列表的好处是,它们在初始化非内置的类成员时提供效率。 例如,

Fred::Fred() : x_(whatever) { }

优于,

Fred::Fred() { x_ = whatever; }

如果x是自定义类的对象。 除此之外,为了保持一致性,甚至使用内置types也使用此样式。

这样做的最普遍的好处是提高了性能。 如果expression式与成员variablesx_的types相同,则expression式的结果直接在x_内部构造 – 编译器不会创build对象的单独副本。

使用其他样式,expression式会导致创build一个单独的临时对象,并将此临时对象传递给x_对象的赋值运算符。 然后那个临时对象被破坏了。 这是无效的。


在使用初始化列表的下面的例子中是否有任何效率增益。 我认为没有收获。 第一个版本调用string的复制构造函数,另一个调用string的赋值运算符(没有任何临时的创build)。 这是正确的?

 class MyClass { public: MyClass(string n):name(n) { } private: string name; }; class MyClass { public: MyClass(string n) { name=n; } private: string name; }; 

第二个版本是调用string的默认ctor,然后是string的复制赋值运算符 – 与第一个版本相比,可以肯定会有(较小的)效率损失,直接调用c的copy-ctor(例如,根据string的实现,可能会无用的分配 – 然后释放一些微小的结构)。 为什么不总是使用正确的方式?)

我认为初始化常量数据成员的唯一方法是在初始化列表中

例如。 在标题中:

 class C { C(); private: const int x; int y; } 

而在cpp文件中:

 C::C() : x( 10 ), y( 10 ) { x = 20; // fails y = 20; } 

这是初始化成员的好方法:

  • 是常量
  • 没有默认的构造函数(它是私有的)

请记住,复制构造函数和赋值运算符有明显的区别:

  • copy ctor使用其他实例构造一个新的对象作为获取初始化信息的地方。
  • 赋值运算符修改已经完全构build的已经存在的对象(即使它只是使用默认的构造函数)

所以在你的第二个例子中,已经做了一些工作来创buildname

  name=n; 

到达了。

然而,这是很有可能的(特别是在这个简单的例子中)所做的工作是微乎其微的(可能只是清理string对象中的一些数据成员),并且工作在优化构build中完全优化。 但是尽可能地使用初始化列表仍然是一种很好的forms。

以下是使用初始化程序列表的场景:

  1. 用于初始化非静态常量数据成员。
  2. 用于初始化参考成员。
  3. 用于初始化没有默认构造函数的成员对象。
  4. 用于基类成员的初始化。
  5. 当构造函数的参数名称与数据成员相同时。
  6. 出于性能原因。

我们也可以通过初始化列表来执行构造函数的委托 。