一、初始化列表
在C++中,初始化列表(Initializer List)是构造函数的一个非常有用的特性,它允许在对象创建时直接初始化成员变量。这通常比先构造对象再调用成员函数设置成员变量的值更高效,尤其是对于那些非基本数据类型(如类类型)的成员变量来说,因为使用初始化列表可以避免不必要的拷贝或移动操作。
二、为甚么要使用初始化列表?
- 效率:对于非基本数据类型的成员变量,使用初始化列表可以避免调用拷贝构造函数。
- 必要性:对于const成员变量和引用成员变量,它们必须在构造函数的初始化列表中初始化,因为一旦构造函数执行完毕,这些成员变量的值就不能再被改变。
- 逻辑清晰:初始化列表使得成员变量的初始化更加直观和集中,易于理解和维护。
三、初始化列表的一些细节
- 每个成员变量在初始化列表中只能出现⼀次,语法理解上初始化列表可以认为是每个成员变量定义
初始化的地⽅。 - 引⽤成员变量,const成员变量,没有默认构造的类类型变量,必须放在初始化列表位置进⾏初始
化,否则会编译报错。
如:
class Time
{
public:
Time(int hour):_hour(hour) /只有有参构造函数
{
}
private:
int _hour;
};
class Date
{
public:
Date(int& x, int year = 1, int month = 1, int day = 1)
:_year(year)
,_month(month)
,_day(day)
,_t(12) /如果不在初始化列表里给没有默认构造函数的_t传值 ,报错:“Time”: 没有合适的默认构造函数可⽤
,_ref(x) /如果不在初始化列表里初始化引用类型,发生报错: 必须初始化引⽤
,_n(1) /如果不在初始化列表里初始化const类型,发生报错:必须初始化常量限定类型的对象
{
/ 函数体内部...
}
private:
int _year;
int _month;
int _day;
Time _t; / 没有默认构造
int& _ref; / 引⽤
const int _n; / const
};
- C++11⽀持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显⽰在初始化列表初始化的
成员使⽤的。 - 尽量使⽤初始化列表初始化,因为那些你不在初始化列表初始化的成员也会⾛初始化列表,如果这
个成员在声明位置给了缺省值,初始化列表会⽤这个缺省值初始化。如果你没有给缺省值,对于没
有显⽰在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有
显⽰在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构
造会编译错误。 - 初始化列表中按照成员变量在类中声明顺序进⾏初始化,跟成员在初始化列表出现的的先后顺序⽆
关。建议声明顺序和初始化列表顺序保持⼀致。
例如:
#include<iostream>
using namespace std;
class A
{
public:
A(int a):_a1(a), _a2(_a1)
{}
void Print() {
cout << _a1 << "," << _a2 << endl;
}
private:
int _a2 = 2;
int _a1 = 2;
};
int main()
{
A aa(1);
aa.Print();
}
输出:1 , 随机值
其中a1的值是1,a2的值是随机值。
原因:初始化列表中按照成员变量在类中声明顺序进⾏初始化! 因为a2需要先初始化,而a1还未初始化,a1的值为随机值,所以给a2初始化为a1的随机值。然后初始化a1,初始化为1。