从概念上讲,可以认为构造函数分为两个阶段执行:
(1)初始化阶段;(2)普通的计算阶段。计算阶段由构造函数函数体中的所有语句组成。
不管成员是否在构造函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段开始之前。
有些成员必须在构造函数初始化列表中进行初始化。对于这样的成员,在构造函数体中对它们赋值不起最用。 没有默认构造函数的类类型成员,以及const或引用类型的成员,不管是哪种类型,都必须在构造函数初始化列表中进行初始化。
因为内置类型的成员不进行隐式初始化,所以对这些成员是进行初始化还是赋值似乎都无关紧要。除了两个例外,对非类类型的数据成员进行赋值或使用初始化式在结果和性能上都是等价的。
记住,可以初始化const对象或引用类型的对象,但不能对它们赋值。在开始执行构造函数的函数体之前,要完成初始化。初始化const或引用类型数据成员的唯一机会是在构造函数初始化列表中。编写该构造函数的正确方式为:
不管成员是否在构造函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段开始之前。
有些成员必须在构造函数初始化列表中进行初始化。对于这样的成员,在构造函数体中对它们赋值不起最用。 没有默认构造函数的类类型成员,以及const或引用类型的成员,不管是哪种类型,都必须在构造函数初始化列表中进行初始化。
因为内置类型的成员不进行隐式初始化,所以对这些成员是进行初始化还是赋值似乎都无关紧要。除了两个例外,对非类类型的数据成员进行赋值或使用初始化式在结果和性能上都是等价的。
例如,下面的构造函数是错误的:
class ConstRef
{
public:
ConstRef(int ii);
private:
int i;
const int ci;
int &ri;
};
ConstRef::ConstRef(int ii)
{
i = ii; //ok
ci = ii; //error
ri = i; //error
}
记住,可以初始化const对象或引用类型的对象,但不能对它们赋值。在开始执行构造函数的函数体之前,要完成初始化。初始化const或引用类型数据成员的唯一机会是在构造函数初始化列表中。编写该构造函数的正确方式为:
ConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii)
{
}