背面经的时候,发现了历史遗留问题,一直没深入理解,今天的摸索中有所进展~
问题:
类成员的初始化方式?构造函数的执行顺序?为什么用成员初始化列表会快一点?
First Q:类的初始化方式
a) 赋值初始化:在函数体内进行初始化;
b)列表初始化:在冒号后使用初始化列表进行初始化。
两者的区别:
赋值初始化:在函数体中进行初始化,在数据成员被分配内存后进行;
列表初始化:在进入函数体前,在数据成员分配内存空间时就进行初始化;
写法如下:
Second Q:构造函数执行顺序
父类:Parent 子类:Child1
父类:有参构造函数 子类:有参构造【初始化列表方式】
父类:无对象 子类:父类对象 p
代码:
class Parent
{
public:
Parent(int x) {
cout << "父类构造:" << x<<endl;
}
~Parent() {
cout << "父类析构" << endl;
}
};
class Chlid1 :public Parent
{
public:
Chlid1(int a,int b):Parent(a),p(b) {
cout << "子类构造函数" << endl;
}
~Chlid1() {
cout << "子类析构函数" << endl;
}
private:
Parent p;
};
int main(){
Chlid1 c(1,2);
return 0;
}
执行顺序:
父类构造函数->子类对象成员构造函数->子类构造函数->子类析构函数->子类对象成员析构函数->父类析构函数
结果如下:
Third Q:为什么初始化列表快一点
**先定义一个 Child 类,在类中定义三个函数:默认构造函数、拷贝构造函数、赋值运算符;
**再定义两个测试类,Test1、Test2;
**Test1 中采用 赋值初始化;
**Test2中采用列表初始化;
如下所示:
class Child2
{
private:
int a;
public:
Child2()
{ cout << "我是无参构造"<< endl; }
Child2(const Child2&)
{
cout << "我是拷贝构造" << endl;
}
Child2& operator=(const Child2&)
{
cout << "我是赋值运算符" << endl;
return *this;
}
};
运行一下,看会出现什么结果:
可以看出,初始化列表的方法不会再次调用无参构造函数和赋值运算符,而是直接调用拷贝构造函数,省去了一次构造函数的步骤。
原因:因为赋值操作是会产生临时变量的,所以调用两次构造函数。