初始化列表
我们知道构造函数的目的是为了初始化。而初始化类的成员有两种方式,一是在构造函数体内进行赋值操作,二就是使用初始化列表。
初始化列表是以冒号开头,后跟一系列以逗号分隔的初始
化字段。
在构造函数体内进行赋值操作:
使用初始化列表:
注:
1.每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使 用初始化列表初始化。
3.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
对于内置类型,如int,double等,使用哪一种方法好像都没有太大的差别,但是对于类类型(该类没有默认构造函数)、引用成员变量、const成员变量这三种来说,必须使用初始化列表。
我们先定义一个A类:
1.无默认构造函数的类类型的自定义类型:
如果像普通的构造函数一样在函数内部进行初始化就会报错,如图
这里就需要使用初始化列表了
class B
{
public:
B(int x, A a)
:_x(x)
,_a(a)
{
}
private:
int _x;
A _a;
};
int main()
{
B b(1, 10);
}
2.引用成员变量
也需要使用初始化列表
class B
{
public:
B(A a, int y)
: _a(a)
, _y(y)
{ }
private:
A _a;
int& _y;
};
3.const成员变量
同样需要使用初始化列表
class B
{
public:
B(int x , A a)
: _x(1)
, _a(a)
{
}
private:
const int _x;
A _a;
};
总结:尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使 用初始化列表初始化。
class A
{
public:
A(int a = 0)
:_a(a)
{ }
private:
int _a;
};
class B
{
public:
B(int x , A a,int y)
: _x(1)
, _a(a)
, _y(y)
{ }
private:
const int _x;
A _a;
int& _y;
};
int main()
{
B b(1, 10, 5);
system("pause");
return 0;
}
可以用调试的方法观察:
注意:成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
例如下面的代码块
class Array
{
public:
Array(int size)
:_size(size)
, _array((int*)malloc(sizeof(int)*_size))
{}
private:
int* _array;
int _size;
};
成员变量在声明时,先去初始化列表中初始化数组,此时数组中的_size未被初始化,为随机值,可能会造成栈溢出。所以,我们尽量将初始化列表中初始化的顺序和声明的顺序写的相同。