以下内容均为本人学习笔记,若有错误,欢迎指正
什么是初始化列表,来看下面代码,我们有一个日期类对象
我们可以这样来定义构造函数:
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
protected:
int _year;
int _month;
int _day;
};
也可以利用初始化列表:
class Date
{
public:
Date(int year,int month,int day)
:_year(year),_month(month),_day(day) //使用初始话列表初始化成员变量
{
}
protected:
int _year;
int _month;
int _day;
};
如上两种方法来定义构造函数,一种是在构造函数体内对成员变量进行初始化,一种是使用 初始化列表来初始化成员变量,都可以达到初始化成员变量的效果,两者有什么区别呢?
在对于内置类型而言,我们还看不出效果
假如有如下需求,我们需要将日期类拓展为时间单位更精确。
//定义一个时间类
class Time
{
public:
Time(int hour = 0,int minute = 0,int second = 0)
{//定义一个全缺省构造函数
_hour = hour;
_minute = minute;
_second = second;
cout<<"Time();"<<endl;
}
protected:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year,int month,int day,int hour,int minute,int second)
{
_year = year;
_month = month;
_day = day;
_time = Time(hour,minute,second);
//创建一个Time类匿名变量来对_t 进行初始化
//这里的完成动作应该是调用一次构造函数
}
protected:
int _year;
int _month;
int _day;
Time _time;//时间类作为日期类的成员变量
};
运行出来结果却是两次,
我们来进行调试看看
为什么使用初始化列表更高效
从图中我们可以看到,在构造函数中,还没有执行到 _t = Time(hour, minute, second);
这一行代码,就已经输出了 Time(),说明已经调用了一次构造函数
事实上,对于自定义类型,一定会在初始化列表处调用一次
即使我们没有自己写初始化列表编译器也会自己调用一次初始化。
所以说如果我们都在初始化列表对变量进行初始化,这样就会更高效一些。
其实我们可以这样说,初始化列表是成员变量定义的地方,也就是为其开辟空间的地方。而类里面只是对变量的声明。
知道了这一点,看看这个问题的答案是什么:
- 哪类变量必须在初始化列表进行初始化?
- 哪些类是必须自己实现构造函数?
我们思考,既然初始化列表是成员变量定义的地方,那就是说,有哪些变量是必须在定义的时候进行初始化,想到这就豁然开朗了,在之前讲过的两类类型
- const类型成员变量
引用类型成员变量
其实还有一点我们应该明确,对于自定义类型,当你没有写初始化列表时,默认只会调用全缺省的构造函数来进行初始化。
没有缺省构造函数的成员变量(必须自己传指定参数实现初始化列表中构造)