目录
[1. const 成员变量](#1. const 成员变量)
[2. 引用成员变量](#2. 引用成员变量)
[3. 没有默认构造函数的自定义类型成员](#3. 没有默认构造函数的自定义类型成员)
一、什么是初始化列表?
在C++中,构造函数除了可以在函数体内给成员变量赋值,也可以使用初始化列表。
普通写法:
cpp
class Date {
public:
Date(int year, int month, int day) {
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
初始化列表写法:
cpp
class Date {
public:
Date(int year, int month, int day)
; _year(year)
, _month(month)
, _day(day)
{
}
private:
int _year;
int _month;
int _day;
};
初始化列表写在构造函数参数列表后面,以冒号 : 开始,多个成员之间用逗号分隔。
二、初始化列表和函数体内赋值有什么区别
函数体内写:
cpp
_year = year;
本是上是赋值。
初始化列表写:
cpp
: _year(year)
本质上是初始化。
简单理解:
cpp
初始化列表:成员函数创建时直接初始化
函数体内赋值:成员变量创建后再赋值
对于普通变量 int、char、double成员你,两种写法很多时候结果一样。
但有些成员必须使用初始化列表。
三、哪些成员必须使用初始化列表
主要有三类:
cpp
1. const 成员变量
2. 引用成员变量
3. 没有默认构造函数的自定义类型成员
1. const 成员变量
cpp
class A {
public:
A(int x)
: _x(x)
{
}
private:
const int _x;
};
const 成员变量创建后不能修改,所以必须在初始化列表中初始化。
2. 引用成员变量
cpp
class A {
public:
A(int x)
: _ref(x)
{
}
private:
int& _ref;
};
引用必须在定义时初始化,所以引用成员也必须使用初始化列表。
3. 没有默认构造函数的自定义类型成员
cpp
class B {
public:
B(int x)
: _x(x)
{
}
private:
int _x;
};
class A {
public:
A(int x)
: _b(x)
{
}
private:
B _b;
};
因为 B 没有无参构造函数,所以 A 中的 _b 必须在初始化列表中显式初始化。
四、初始化顺序
成员变量的初始化顺序不是看初始化列表中的书写顺序,而是看成员变量在类中的声明顺序。
例如:
cpp
class A {
public:
A(int x)
: _a1(x)
, _a2(_a1)
{
}
private:
int _a2;
int _a1;
};
虽然初始化列表中先写 _a1,但成员变量声明时 _a2 在前,所以实际会先初始化 _a2。
因此建议:
初始化列表的书写顺序和成员变量的声明顺序保持一致。
这样代码更清晰,也不容易出错。
五、小结
本篇主要学习了构造函数初始化列表。
需要记住:
- 初始化列表写在构造函数参数列表后面;
- 初始化列表以 : 开始;
- 多个成员变量之间用逗号隔开;
- 函数体内是赋值,初始化列表才是初始化;
- const 成员变量必须使用初始化列表;
- 引用成员变量必须使用初始化列表;
- 没有默认构造函数的自定义类型成员必须使用初始化类表;
- 成员变量初始化顺序由声明顺序决定;
- 初始化列表书写顺序建议和成员声明顺序保持一致;
- 建议优先使用初始化列表写构造函数。
初始化列表是构造函数中的重要内容。理解它之后才能更好的处理 const 成员、引用成员和自定义类型成员的初始化问题。