相对于在构造函数体中用显式的赋值语句来设置成员变量的值,还有另一种更高效的技术,即使用成员初始化列表。
下面使用类 Box 的构造函数的另一个版本来说明:
Box::Box(double lv, double wv, double hv):length {lv}, width {wv}, height {hv}
{
std::cout << "Box constructor called." << std::endl;
}
成员变量的值在构造函数头的初始化列表中被指定为初始值。例如,成员变量 length 用 lv 初始化。构造函数的初始化列表与参数列表用冒号分隔开,每个初始值用逗号分隔开。
在使用构造函数体中的赋值语句初始化成员变量时,首先要创建成员变量(如果这是类的一个实例,就调用构造函数),再执行赋值语句。如果使用初始化列表,成员变量在被创建时,就用初始值对它进行初始化。效率要比在构造函数体中使用赋值语句高得多,特别是在成员变量是一个类实例时,就更是如此。
有一个地方需要注意:成员变量的初始化顺序由类定义中声明成员变量的顺序决定。因此,可能与读者预期的不同,并不是按照它们在成员初始化列表中出现的顺序进行初始化。当然,只有当使用表达式来初始化成员变量时,或者当通过调用一个成员函数来初始化变量,但是该成员函数依赖于另一个已经初始化的成员变量时,就会出现这种情况。在生产中依赖这种计算顺序可能很危险。即使今天所有代码都正常工作,但是明年,其他人可能改变声明顺序,导致类的构造函数不再正确。
一般来说,首选在构造函数的成员初始化列表中初始化所有成员变量。这样做一般更加高效,为了避免产生混淆,最好按照类定义中成员变量的声明顺序,在初始化列表中列举成员变量。只有当需要更加复杂的逻辑时,或者当初始化成员变量的顺序很重要时,才应该在构造函数内初始化成员变量。