初始化列表初始化列表用于初始化构造函数的参数。 与其他函数不同,构造函数除了名称、参数列表和函数主体外,还包含一个初始化列表,其中以冒号开头,后跟一系列用逗号分隔的初始化字段。
例如:
class my clock { public : my clock (inthh,int mm,int ss ); //构造函数声明private: int hour,minu,second; (; //构造函数实现和初始化设置myclock:3360myclock(inthh,int mm,int ss ) :hour ) hh )、minu ) mm )、 second ) ss ) { cout '初始化完成) Endddron }如上所述,构造函数的实现部分使用初始化列表初始化myClock类中的三个数据成员hour、minu和second
后面的:号之后的hour(hh )、minu ) mm )、second ) ss )三者实际上等价于以下内容。
hour=hh; minu=mm; second=ss; 因此,它等效于执行了赋值操作,即初始化操作。
所以,我们的构造函数的实现和初始化设置也可以这样写:
class my clock { public : my clock (inthh,int mm,int ss ); //构造函数声明private: int hour,minu,second; (; //构造函数实现和初始化设置myclock:3360myclock(inthh,int mm,int ss ) ) { hour=hh; minu=mm; second=ss; cout '初始化完成' endl; }虽然实现了与以前完全相同的功能,但是效率比初始化列表差一些。 因此,主要是性能问题。 当然,在int、float等嵌入式类型中,使用初始化类表和在构造函数中进行初始化的差别不大,但为什么最好在内嵌类的类型中使用初始化列表对于数据密集型类来说,初始化列表非常高效,因为调用缺省构造函数的过程较少。
组合类的构造函数和复制构造函数如上分析后,发现对于组合类(内嵌类),最好使用初始化列表进行初始化,所以使用初始化列表对构造函数和复制构造函数进行初始化最初以为是因为组合类的构造函数和复制构造函数与普通类不同,但调查了资料后发现,普通类和组合类的构造函数和复制构造函数声明形式、实现形式是完全相同的类的构造函数和复制构造函数组合在初始化代入时充分利用了初始化列表
所以书上写道:
组合类的构造函数定义的一般格式如下:
//组合类的构造函数
类名:类名(形参表):内嵌对象1(形参表1),内嵌对象2(形参表2),......
{
函数体内部;
}
类的复制构造函数定义的一般格式如下:
组合//类的复制构造函数
类名:类名(以类名命名的对象名称):内嵌对象1(对象名.内嵌对象1),内嵌对象2(对象名.内嵌对象2)......
{
函数体内部;
}
这两个函数的定义在冒号前部分与普通类完全相同,从
:号开始,是运用了初始化列表,所以看起来和普通类不同而已,其实普通类和组合类的构造函数和复制构造函数形式是一样的。上述定义其实就是:
//组合类的构造函数
类名::类名(形参表)
{
内嵌对象1 = 形参表1;
内嵌对象1 = 形参表2;
......
函数体内部;
}
//组合类的复制构造函数
类名::类名(类名 &命名的对象名)
{
内嵌对象1 = 对象名.内嵌对象1
内嵌对象2 = 对象名.内嵌对象2
......
函数体内部;
}
理解了初始化列表,也就理解了书上所说的组合类的构造函数和复制构造函数的实现形式的奇怪之处,事实上,除了性能问题之外,有些时候合初始化列表是不可或缺的。
以下几种情况时必须使用初始化列表:
1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面。
2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面。
3. 没有默认构造函数的内嵌类的类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用复制构造函数初始化。