构造函数初始化列表

时间:2021-03-28 19:39:07

转自http://blog.csdn.net/gzshun

从概念上讲,可以认为构造函数分两个阶段进行:

1.初始化阶段;
2.普通的计算阶段。(计算阶段由构造函数函数体中的所有语句组成)
不管成员是否在构造函数初始化列表中显示初始化,类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段的开始之前。
建议:使用构造函数初始化列表
注:必须对任何const或引用类型成员以及没有默认构造函数的类类型的任何成员使用初始化式。
一般使用构造函数初始化列表,可以避免发生编译错误。
讲解:没有默认构造函数的类?是什么意思?
在大部分编译器中,声明一个类,若类没有显示的声明和定义构造函数,那么编译器就会在编译阶段生成一个默认构造函数。如果用户在该类中声明了一个构造函数,那么编译器就不会生成默认构造函数,而是使用了用户自己定义的构造函数,为了避免编译错误,最好使用构造函数初始化列表对该类的对象进行初始化。
-----摘自于《C++ Primer 中文版 第4版》

类成员的初始化包括类对象成员与类数据成员的初始化。初始化比较关键的是构造函数的初始化列表,在构造函数中成员初始化列表中也需要次序的。只有构造函数才能有成员初始化的效果,普通的成员函数没有这功能,比如:

[cpp] view plaincopy
  1. void CInit::setXY(int x, int y) : mX(x), mY(y)  
  2. {  
  3. }  
这个初始化是错误的,setXY并非是构造函数,所以普通成员函数只能通过赋值的形式来设置变量或对象的值。

[cpp] view plaincopy
  1. void CInit::setXY(int x, int y)  
  2. {  
  3.      mX = x;  
  4.      mY = y;  
  5. }  
这里声明一个类CInit,如下:

[cpp] view plaincopy
  1. class CInit  
  2. {  
  3. public:  
  4.     CInit(int x, int y);  
  5.     void Show() const;  
  6. private:  
  7.     int mX;  
  8.     int mY;  
  9. };  
  10. void CInit::Show() const  
  11. {  
  12.     cout << "mX = " << mX << endl  
  13.          << "mY = " << mY << endl;  
  14. }  

一.构造函数的初始化列表的基本使用
这是正常的初始化列表的用法
初始化:

[cpp] view plaincopy
  1. CInit::CInit(int x, int y) : mX(x), mY(y)  
  2. {  
  3. }  
达到的结果相当于
赋值:

[cpp] view plaincopy
  1. CInit::CInit(int x, int y)  
  2. {  
  3.     mX = x;  
  4.     mY = y;  
  5. }  

二.成员初始化的次序
在构造函数初始化列表中,成员初始化的次序就是声明成员的次序。
例子1:张三想先用x初始化mX,再用mX初始化mY

[cpp] view plaincopy
  1. CInit::CInit(int x, int y) : mX(x), mY(mX)  
  2. {  
  3. }  
  4. CInit test(2, 3);  
  5. test.Show();  
此时的结果是:

[plain] view plaincopy
  1. mX = 2  
  2. mY = 2  
mX与mY均被成功的初始化。


例子2:李四想先初始化mY,再用mY初始化mX

[cpp] view plaincopy
  1. CInit::CInit(int x, int y) : mY(y), mX(mY)  
  2. {  
  3. }  
  4. CInit test(2, 3);  
  5. test.Show();  
此时的结果是:

[plain] view plaincopy
  1. mX = 2147344384  (不同机器可能不一致)  
  2. mY = 3  
从结果可以很明显的看出,mX没有被初始化,而mY成功被初始化为3。


从这里可以看出,构造函数是以变量的声明顺序来执行初始化的动作,所以例子2中,构造函数先初始化mX,但此时mY是未初始化过的,所以导致这种情况。在构造函数的初始化列表中,最好要按照类中成员变量的声明顺序来初始化。


三.在什么情况下使用构造函数初始化列表?
1.const对象
2.引用类型对象
因为const对象与引用类型对象只能够初始化,不能赋值,所以必须在初始化列表中进行初始化。
3.类对象(下文说明)