赞
踩
《C++ Primer Plus》中这样描述:从概念上来说,调用构造函数时,对象将在括号中的代码被执行之前被创建。因此,调用构造函数将导致程序先给其成员变量分配内存。然后,程序流程进入到括号中,使用常规的赋值方式将值存储到内存中。
我们将构造函数分为两个先后过程:
1.初始化阶段。创建对象,给成员变量分配内存。调用构造函数时,创建对象,隐式/显示的初始化各数据成员(给其成员变量分配内存);
2.赋值计算阶段。进入构造函数体中执行一般赋值与计算操作。
与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。
成员初始化列表只能在构造函数中使用。
对于类成员中含有一个const(常量)对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化。
因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。所以必须在执行到构造函数体之前,即在对象被创建时进行初始化。
class A
{
priate:
const int a; //const修饰成员
public:
A():a(10){} //初始化
};
class B
{
private:
int &b; //被声明为引用
public:
B(int b):b(b){} //初始化
}
如果一个类成员本身就是一个类或者一个结构,并且这个成员只有一个带参数的构造函数,没有无参数的构造函数;这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错。
class A { public: A (int, int){ }; private: //类成员为x,y int x; int y; }; class B { public: B():a(1,2),z(z){ //初始化 }; private: A a; //B的另一个类成员为一个A的类对象, 类对象作为类成员 int z; };
子类初始化父类的私有成员,需要在(并且也只能在)参数初始化列表中显示调用父类的构造函数。
class Test{ public: Test(){}; Test (int x){ int_x = x;}; void show(){cout<< int_x << endl;} private: int int_x; }; class Mytest:public Test{ public: Mytest() :Test(110){ //Test(110); // 构造函数只能在初始化列表中被显示调用,不能在构造函数内部被显示调用 }; }; int main() { Test *p = new Mytest(); p->show(); return 0; }
其一:C++语法规定使然。
其二:主要是性能问题,对于内置类型,如int, float等,使用初始化类表和在构造函数体内初始化差别不是很大,但是对于类类型来说,最好使用初始化列表。
为什么呢?
使用初始化列表少了一次调用默认构造函数的过程,这对于数据密集型的类来说,是非常高效的。
所以一个好的原则是,能使用初始化列表的时候尽量使用初始化列表.
数据成员被初始化的顺序与他们出现在类声明中的顺序相同,与初始化器中的排列顺序无关。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。