初始化列表的好处

Ank*_*kur 40 c++ initialization-list

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

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

比较好,

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

如果x是自定义类的对象.除此之外,为了保持一致性,这种风格甚至与内置类型一起使用.

这样做的最常见好处是提高了性能.如果表达式与成员变量x_的类型相同,则任何表达式的结果都直接在x_中构造 - 编译器不会创建该对象的单独副本.

使用另一种样式,表达式可以创建单独的临时对象,并将此临时对象传递给x_对象的赋值运算符.然后该临时对象在;处被破坏.那效率很低.

问题
使用初始化列表,以下示例中是否存在任何效率增益.我认为没有收获.第一个版本调用字符串的复制构造函数,另一个调用字符串的赋值运算符(没有创建任何临时的).这是正确的吗?

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

class MyClass
{
public:
    MyClass(string n)
    {
        name=n;
    }
private:
    string name;
};
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 33

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

  • 真正.你还应该提到,有时候,"正确的方法"是你唯一的选择.如果你需要初始化一个引用或一个const类型,或者没有赋值操作符的东西,你就没有多少选择了 (2认同)

pxb*_*pxb 15

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

例如.在标题中:

class C
{
    C();
private:
    const int x;
    int y;
}
Run Code Online (Sandbox Code Playgroud)

并在cpp文件中:

C::C() :
    x( 10 ),
    y( 10 )
{
    x = 20; // fails
    y = 20;
}
Run Code Online (Sandbox Code Playgroud)


Mac*_*iek 13

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

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


Mic*_*urr 11

请记住,复制构造函数和赋值运算符之间存在明显差异:

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

因此,在你的第二个例子,一些工作已经完成创建name由时间

 name=n;
Run Code Online (Sandbox Code Playgroud)

到达了.

但是,很有可能(特别是在这个简单的例子中)完成的工作非常小(可能只是将string对象中的一些数据成员归零)并且工作在优化的构建中完全被优化掉了.但是尽可能使用初始化程序列表仍然是一种很好的形式.