构造函数的深入理解_初始化列表

    说到构造函数,就必须要说到构造函数初始化列表。为什么要说它呢,下面来给各位客官娓娓道来。(目前有许多博客对此处已经说的很好了,可是沙米在前篇给大家写了构造函数的理解和应用场景博客后,还想让大家再深入的理解一下,故做此文章)

    构造函数进化流程:

    124641_HwvT_1783725.png

    现在来详细聊聊:

    1、使用格式

    构造函数的初始化列表以冒号开头,后面跟着一系列以逗号分隔的初始化字段。

class Teacher
{
public:
	Teacher(int x):i(x),j(x){}; //初始化列表
private:
	int i;
	int j;
};

 

    2、  构造函数执行的两个阶段

    初始化阶段:所有类类型(class type)的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中。

    计算阶段:一般用于执行构造函数体内的赋值操作

    使用常规构造函数赋值类对象:

#include <iostream>
using namespace std; 

class Test_A
{
public:
	Test_A()
	{
		cout<<"构造函数Test_A()"<<endl;
	}

	Test_A(const Test_A& t1)
	{
		cout<<"拷贝构造函数Test_A()"<<endl;
		m_age = t1.m_age;
	}

	Test_A& operator = (const Test_A& t1)
	{
		cout<<"重载赋值运算符operator="<<endl;
		m_age = t1.m_age;
		return *this;
	}

	~Test_A()
	{
		cout<<"析构函数~Test_A()"<<endl;
	}
public:
	int m_age;
};

class Test_B
{
public:
	Test_B(Test_A& t1)
	{
		m_b = t1;
	}
public:
	Test_A m_b;
};

/*此函数相当于一个舞台,展示此函数内对象的完整生命周期*/
void display() 
{
	Test_A t1;
	Test_B t2(t1);
}

int main()
{
	display();
	system("pause");
	return 0;
}

 

    输出结果:

构造函数Test_A()
构造函数Test_A()
重载赋值运算符operator=
析构函数~Test_A()
析构函数~Test_A()

 

    从输出结果中可以看出,在执行Test_B t2(t1)的过程:

            先调用Test_A类的构造函数初始化成员对象 m_b                         (初始化阶段)

            然后再调用Test_A类的重载赋值运算符函数,将t1赋值给m_b。    (计算阶段)

    使用初始化列表(只需修改类Test_B中的构造函数):

class Test_B
{
public:
	Test_B(Test_A& t1):m_b(t1){};   //使用了构造函数的初始化列表
public:
	Test_A m_b;
};

 

        输出结果:

构造函数Test_A()
拷贝构造函数Test_A()
析构函数~Test_A()
析构函数~Test_A()

 

     从输出结果中可以看出,执行Test_B t2(t1)的过程:

    在初始化成员对象 m_b时,直接调用Test_A类的拷贝构造函数进行初始化。(初始化阶段)

                                无                                                                                 (计算阶段)

143007_d7Lq_1783725.png

     3、为什么需要——初始化列表

    (1)性能的提高,对于内置类型,使用初始化列表和构造函数内赋值性能差别不是很大,但是对于类类型来说,使用初始化列表,减少了一次计算阶段,如果是密集型类,效率将会更高。

    (2) 成员的类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败,必须使用初始化列表

    (3)const成员或引用类型的成员。因为const对象或引用类型只能初始化,不能对他们赋值,必须使用初始化列表

      注意:类中成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的

    4、本质(很重要)

    在执行A类构造函数的初始化阶段,就将传入A类构造函数的参数值在A类的成员初始化时,进行了值得传递。

    沙米才疏学浅,希望大家多多给沙米提意见。,一起进步,提高。

转载于:https://my.oschina.net/u/1783725/blog/652295

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值