在下列情况下,为了让你的程序能够被顺利编译,你必须使用member initialization list
- 当初始化一个
reference member
时; - 当初始化一个
const member
时; - 当调用一个
base class
的constructor,而它拥有一组参数时 - 当调用一个
member class
的constructor
,而它拥有一组参数时;
考虑如下代码:
class Word {
string _name;
int _cnt;
public:
Word() {
_name = 0;
_cnt = 0;
}
};
以下为上述构造函数代码的内部扩张结果:
Word::Word(/*this 指针*/) {
// 调用string的default constructor
_name.string::string();
// 产生临时对象
string temp = string(0);
// memberwise的拷贝_name
_name.string::operator=(temp);
// 摧毁临时对象
temp.string::~string();
_cnt = 0;
}
对代码反复审查并且修正,可以得到一个更有效率的实现方法:
Word::Word(): _name(0){
_cnt = 0;
}
它会被扩张成这个样子:
Word::Word(/*this 指针*/){
// 调用string(int) constructor
_name.string::string(0)
_cnt = 0;
}
list
中的项目顺序是由class
中的members
声明顺序决定的,不是由initialization list
中的排列顺序决定的; 如:
Class X {
int i;
int j;
public:
X(int val) : j(val), i(j){}
};
上述代码看起来像是要把j设初始值为val
,再把i
设初值为j
.问题在于,由于声明顺序的缘故,initialization list
中的i(j)
其实比j(val)
更早执行.
建议的做法是总是把一个member
的初始化操作和另一个放在一起:
X::X(int val) : j(val) {
i = j;
}
还有一个有趣的问题,initialization list
中的项目被安插到constructor
,会继续保持声明顺序么?也就是说j
的初始化操作会被安插在explicit user assigment
操作(i=j)之前还是之后?;答案是之前,因为initialization list
的项目被放在explicit user code
之前;