1、必须用初始化列表的场景
(1)成员变量是引用类型,必须在初始化列表中初始化。
(2)成员变量是const类型,必须在初始化列表中初始化。
(3)如果类继承自一个父类,并且父类中有带初始化列表的构造函数,必须在初始化列表中初始化父类。
class Base {
public:
Base(int i) { }
};
class Derive:public Base {
public:
Derive(int i) : Base(i){}
};
(4)成员变量是类类型,且这个类的构造函数带参数。
class Item {
public:
Item(int i) { }
};
class MyDemo {
public:
MyDemo(int i) : item(i){}
Item item;
};
2、初始化列表的执行时机
初始化列表是在构造函数之前执行的。
我们可以用下面的代码来验证:
class Item {
public:
Item() { }
Item(const Item& _item) {
cout << " Item拷贝构造函数" << endl;
}
};
class Derive {
public:
Derive() { cout << " Derive默认构造函数" << endl; }
Derive(Item& _item) : item(_item) { cout << " Derive带初始化列表构造函数" << endl; }
Item item;
};
int main()
{
Item _item;
Derive derive(_item);
return 0;
}
执行结果如下:
从运行结果看,初始化列表是在构造函数之前运行的。
3、按成员变量的声明顺序初始化,而不是根据初始化列表中的前后顺序。
class X{
public:
X(int val) : j(val), i(j){}
private:
int i;
int j;
}
其实在这个时候,构造函数是这么初始化的:
X::X(int val){
i = j;
j = val;
}
所以最终的结果是j = val, 但i的值未知。
4、初始化列表的优点
一般地,放在构造函数初始化列表中进行初始化,比放在构造函数中初始化效率更高。
我们可以通过代码来验证这个结论:
(1)构造函数中初始化
class Item {
public:
Item() {
cout << " Item默认构造函数" << endl;
}
Item(int i) {
cout << " Item(int)构造函数" << endl;
}
Item(const Item& _item) {
cout << " Item拷贝构造函数" << endl;
}
Item& operator = (const Item& _item) {
cout << " Item拷贝赋值运算符" << endl;
return *this;
}
};
class Derive {
public:
Derive(int i){
item = Item(i);
cout << " Derive带初始化列表构造函数" << endl;
}
Item item;
};
int main()
{
Derive derive(2);
return 0;
}
运行结果:
(2)初始化列表中初始化
Derive(int i) : item(i){}
运行结果:
可以看到,初始化列表初始化时少了1次默认构造函数和1次拷贝赋值运算符。