C++为什么需要成员初始化列表

转自:http://blog.csdn.net/ws1347913745/article/details/8682331

将构造函数分为两个阶段的执行过程:初始化阶段和构造函数函数体阶段。

既然称它为成员初始化列表,那么该阶段在初始化阶段完成。

那么类成员变量不外乎类类型和非类类型。而对于非类类型而言,此时

无论是在初始化表中还是函数体内完成赋值效果是一致的,即并未初始化。

表现的有点不同的是类类型:

test1:

 1 #include<iostream>
 2 using namespace std;
 3 class B
 4 {
 5 public:
 6     B()
 7     {
 8         cout<<"B()"<<endl;
 9     }
10     B(int i)
11     {
12         cout<<"B(int i)"<<endl;
13     }
14 };
15 class A
16 {
17 public:
18     A()
19     {
20         cout<<"A()"<<endl;
21     }
22 private:
23     B b;
24 };
25 int main()
26 {
27     A a;
28     return 0;
29 }

 

B类的默认构造函数被调用来初始化 b 对象了,也就是说对于类类型对象将调用它的默认构造函数完成初始化。

如果在成员初始化列表中显示地用B类接收int 形参的构造函数会怎么样:

test2:

 1 #include<iostream>
 2 using namespace std;
 3 class B
 4 {
 5 public:
 6     B()
 7     {
 8         cout<<"B()"<<endl;
 9     }
10     B(int i)
11     {
12         cout<<"B(int i)"<<endl;
13     }
14 };
15 class A
16 {
17 public:
18     A()
19     {
20         cout<<"A()"<<endl;
21     }
22 private:
23     B b;
24 };
25 int main()
26 {
27     A a;
28     return 0;
29 }

 

B成员的对象直接调用了带int形参的构造函数,利用成员初始化列表我们完成了类成员的初始化工作。

那如果将他放入函数体中呢:

test3:

 1 #include<iostream>
 2 using namespace std;
 3 class B
 4 {
 5 public:
 6     B()
 7     {
 8         cout<<"B()"<<endl;
 9     }
10     B(int i)
11     {
12         cout<<"B(int i)"<<endl;
13     }
14 };
15 class A
16 {
17 public:
18     A()
19     {
20         cout<<"A()"<<endl;
21     }
22 private:
23     B b;
24 };
25 int main()
26 {
27     A a;
28     return 0;
29 }

 

可以看见,它同样可以达到想要的结果,可是此时我们期望的是利用带参数的构造函数初始化B类对象,并不期望多此一举的

先调用默认构造。而之所以这样就是因为我们并未将初始化在函数体之前完成,而是将它带入了函数体。

所以,对于类类型对象的成员变量初始化过程:

1 编译器发现有类对象的定义时,首先找到了成员初始化列表,如果未找到相应的初始化定义,

则调用类的默认构造函数来完成初始化。找到则采用列表中的定义。

2 如果用户希望采取非默认构造初始化对象,而有将其放在函数体中,则此时一定要为该类提供默认的

构造函数,否则编译报错。

3 可以看出,如果你显示定义了带参构造,那么总是为类提供一个默认的构造函数是好的习惯,可以帮你避免许多可能麻烦。

4 对于某些必须在定义的同时初始化的变量,成员初始化列表就是非用不可的了,如const或则是引用类型,否则编译报错。

5 注意上面所说的是类类型成员对象的表现,而非引用或指针的表现。

特殊的成员:static成员它是在什么时候初始化的呢?答案是在第一次用到该成员时,因为static成员在内存中只有一份的拷贝,

它在整个程序阶段只被初始化一次。可以往A中加入static变量定义,发现实例化A对象后static变量未被初始化。

 

总之。如何利用好成员的初始化列表还是很重要的。

posted @ 2017-04-29 17:38  willhua  阅读(492)  评论(0编辑  收藏  举报