一、什么是初始化列表?
以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
class Date
{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
二、为什么要使用初始化列表?
对于一般的成员函数,使用初始化列表初始化和在构造函数体内初始化是一样的,如下所示:
class Date
{
public:
Date(int year, int month, int day) //
: _year(year)
, _month(month)
, _day(day)
{}
Date(int year, int month, int day) //效果一样
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
但是对于:引用成员变量、const成员变量、自定义类型成员(该类没有默认构造函数) , 必须使用初始化列表进行初始化。
对于引用和const成员变量,不接受定义后的赋值,而private中只是进行声明并没有定义,因此C++规定将其放在初始化列表进行定义并且赋值。
C++类的构造函数的调用顺序是先父类构造、再成员类对象调用构造、最后才是调用自身的构造函数。因此如果成员对象并没有默认构造函数(即不需要参数就能调用的构造函数)就必须给其传参数去调用带参的构造函数。初始化列表的执行要早于构造函数体,因此要将自定义类型成员放在初始化列表中初始化。
class A
{
public:
A(int a)
:_a(a)
{}
private:
int _a;
};
class B
{
public:
B(int a, int ref)
:_aobj(a)
,_ref(ref)
,_n(10)
{}
private:
A _aobj; // 没有默认构造函数
int& _ref; // 引用
const int _n; // const
};
三、初始化列表初始化的顺序和什么有关?
成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。
class A
{
public:
A(int a)
:_a1(a) //生命顺序是_a2 _a1,因此会先将_a1的值先赋给_a2,再将a的值赋给_a1
,_a2(_a1)
{}
void Print()
{
cout<<_a1<<" "<<_a2<<endl;
}
private:
int _a2;
int _a1;
}
int main()
{
A aa(1); //因此输出的是1 和 随机数
aa.Print();
}