构造函数的深入理解_初始化列表
2016-04-04 00:00
148 查看
摘要: 构造函数进化流程、初始化列表的使用和本质
说到构造函数,就必须要说到构造函数初始化列表。为什么要说它呢,下面来给各位客官娓娓道来。(目前有许多博客对此处已经说的很好了,可是沙米在前篇给大家写了构造函数的理解和应用场景博客后,还想让大家再深入的理解一下,故做此文章)
构造函数进化流程:
现在来详细聊聊:
1、使用格式
构造函数的初始化列表以冒号开头,后面跟着一系列以逗号分隔的初始化字段。
2、 构造函数执行的两个阶段
初始化阶段:所有类类型(class type)的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中。
计算阶段:一般用于执行构造函数体内的赋值操作
使用常规构造函数赋值类对象:
输出结果:
从输出结果中可以看出,在执行Test_B t2(t1)的过程:
先调用Test_A类的构造函数初始化成员对象 m_b (初始化阶段)
然后再调用Test_A类的重载赋值运算符函数,将t1赋值给m_b。 (计算阶段)
使用初始化列表(只需修改类Test_B中的构造函数):
输出结果:
从输出结果中可以看出,执行Test_B t2(t1)的过程:
在初始化成员对象 m_b时,直接调用Test_A类的拷贝构造函数进行初始化。(初始化阶段)
无 (计算阶段)
3、为什么需要——初始化列表
(1)性能的提高,对于内置类型,使用初始化列表和构造函数内赋值性能差别不是很大,但是对于类类型来说,使用初始化列表,减少了一次计算阶段,如果是密集型类,效率将会更高。
(2) 成员的类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败,必须使用初始化列表
(3)const成员或引用类型的成员。因为const对象或引用类型只能初始化,不能对他们赋值,必须使用初始化列表
注意:类中成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的
4、本质(很重要)
在执行A类构造函数的初始化阶段,就将传入A类构造函数的参数值在A类的成员初始化时,进行了值得传递。
沙米才疏学浅,希望大家多多给沙米提意见。,一起进步,提高。
说到构造函数,就必须要说到构造函数初始化列表。为什么要说它呢,下面来给各位客官娓娓道来。(目前有许多博客对此处已经说的很好了,可是沙米在前篇给大家写了构造函数的理解和应用场景博客后,还想让大家再深入的理解一下,故做此文章)
构造函数进化流程:
现在来详细聊聊:
1、使用格式
构造函数的初始化列表以冒号开头,后面跟着一系列以逗号分隔的初始化字段。
[code=plain]class Teacher { public: Teacher(int x):i(x),j(x){}; //初始化列表 private: int i; int j; };
2、 构造函数执行的两个阶段
初始化阶段:所有类类型(class type)的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中。
计算阶段:一般用于执行构造函数体内的赋值操作
使用常规构造函数赋值类对象:
[code=plain]#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; }
输出结果:
[code=plain]构造函数Test_A() 构造函数Test_A() 重载赋值运算符operator= 析构函数~Test_A() 析构函数~Test_A()
从输出结果中可以看出,在执行Test_B t2(t1)的过程:
先调用Test_A类的构造函数初始化成员对象 m_b (初始化阶段)
然后再调用Test_A类的重载赋值运算符函数,将t1赋值给m_b。 (计算阶段)
使用初始化列表(只需修改类Test_B中的构造函数):
[code=plain]class Test_B { public: Test_B(Test_A& t1):m_b(t1){}; //使用了构造函数的初始化列表 public: Test_A m_b; };
输出结果:
[code=plain]构造函数Test_A() 拷贝构造函数Test_A() 析构函数~Test_A() 析构函数~Test_A()
从输出结果中可以看出,执行Test_B t2(t1)的过程:
在初始化成员对象 m_b时,直接调用Test_A类的拷贝构造函数进行初始化。(初始化阶段)
无 (计算阶段)
3、为什么需要——初始化列表
(1)性能的提高,对于内置类型,使用初始化列表和构造函数内赋值性能差别不是很大,但是对于类类型来说,使用初始化列表,减少了一次计算阶段,如果是密集型类,效率将会更高。
(2) 成员的类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败,必须使用初始化列表
(3)const成员或引用类型的成员。因为const对象或引用类型只能初始化,不能对他们赋值,必须使用初始化列表
注意:类中成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的
4、本质(很重要)
在执行A类构造函数的初始化阶段,就将传入A类构造函数的参数值在A类的成员初始化时,进行了值得传递。
沙米才疏学浅,希望大家多多给沙米提意见。,一起进步,提高。
相关文章推荐
- mongodb 添加用户和验证
- for my life
- 关于 find_in_set 的性能问题
- 第四节课 上半身训练
- CentOS6.5 ping: unknown host 解决方
- win7 任务管理器找不到关闭按钮
- chm文档已取消到该网页的导航的解决方法
- 如何用手机浏览电脑上的本地网站(PHP+Mysql+Apache环境)
- word论文中的多级列表,帮助您随心所欲的设定标题
- [10秒学会] - runtime之添加动态属性
- Xcode免证书调试
- Java的方法
- Java构造方法(构造函数)
- 企业级监控系统之二cacti
- hadoop完全分布式集群搭建
- logcat 日志 注解
- Toast提示框 注解
- 幸运大转盘
- iOS弹跳动画
- PHP中刷新输出缓冲