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次拷贝赋值运算符。