我所知道的使用初始化列表的好处是它们在初始化非内置的类成员时提供了效率。例如,
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;
};
答案 0 :(得分:33)
第二个版本调用字符串的默认ctor,然后是字符串的复制赋值运算符 - 与第一个版本相比,肯定存在(次要的)效率损失,它直接调用c的copy-ctor(例如,取决于字符串的实现,可能会有一些无用的分配 - 然后释放一些微小的结构)。为什么不总是以正确的方式使用? - )
答案 1 :(得分:15)
我认为初始化const数据成员的唯一方法是在初始化列表中
EG。在标题中:
class C
{
C();
private:
const int x;
int y;
}
在cpp文件中:
C::C() :
x( 10 ),
y( 10 )
{
x = 20; // fails
y = 20;
}
答案 2 :(得分:13)
这是初始化成员的好方法:
答案 3 :(得分:11)
请记住,复制构造函数和赋值运算符之间存在明显差异:
所以在你的第二个例子中,到目前为止已经完成了一些工作来创建name
name=n;
达到。
然而,很有可能(特别是在这个简单的例子中)完成的工作非常小(可能只是将string
对象中的一些数据成员归零)并且工作在优化中完全优化了建立。但是,只要有可能,它仍然被认为是使用初始化程序列表的好形式。
答案 4 :(得分:11)
以下是使用初始化列表时的方案:
答案 5 :(得分:2)
我们也可以通过初始化列表执行constructor delegation。