initialization member list

initialization member list

当以下情况,适于使用initialization member list对其进行初始化

  • 初始化一个reference member
  • 初始化一个const member
  • 初始化constructor具有参数的base class
  • 初始化constructor具有参数的member class

如果没有使用initialization member list对变量进行初始化,而在函数内对其进行赋值操作,注意,是赋值,而不是初始化,那么效率就会变低

如果一个变量没有被显式初始化,那么就会隐式调用该变量的constructor,然后产生一个临时变量,再进行赋值操作,那么代价就是两次初始化,一次拷贝,一次析构

1
2
3
4
5
6
7
8
String str;

Constructor() {
str = String::String();
String temp = String(0);
str.String::operator=(temp);
temp.String::~String();
}

如果使用了initialization member list,代码会变成这样

1
2
3
4
5
Constructor():str(0) {}
||
Constructor() {
str.String::String(0);
}

值得注意的是,初始化的顺序由定义顺序决定

1
2
3
4
5
6
String str;
int number;

Constructor() : number(0), str("nice") {}
||
Constructor() : str("nice"), number(0) {}

也就是说人为安排初始化顺序是无用功,因为不会受人为安排的顺序影响,只与变量定义有关

1
2
3
int number;
int i;
Constructor() : i(0), number(i) {}

上面这段代码则是错误的,因为number先定义,那么number(i)则是未知取值

同样,关于初始化的问题,还有另一种形式

1
2
3
X::X(int val) : i(xfoo(val)) {

}

这种形式的初始化,如果xfoo()存在于class之内,那么就十分危险,如果xfoo()的正确执行依赖于其他class member的初始化,那么就会导致bug

如果使用derived classmember来初始化base class,也有可能会出现bug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo : public x {
private:
int _fval;
public:
int fval() {return _fval;}
Foo(int val) : fval(val), X(fval()) {

}
}

//其中Foo可能会被扩充为
Foo(int val) {
X::X(this, this->fval());
_fval = val;
}

其中大概的原因是

base class会先被初始化,然后才到derived class的初始化