标签:cc++
#include <iostream> using namespace std; class A{ public: A(int a,string str) { m_a = a; m_str = str; } //A(int a,string str):m_a(a),m_str(str){} void print() { cout << m_a << ' '<< m_str<< endl; } private: int m_a; string m_str; }; int main(int argc, char **argv) { A a(1,"hello"); a.print(); return 0; }
运行结果相同,那么两者区别在哪里???
从概念上,我们可以认为构造函数分两个阶段执行:
(1)初始化阶段 (2)普通的计算阶段。
①不管成员是否在构造函数初始化列表中显式初始化, 类类型的数据成员总是会在初始化阶段初始化。 初始化发生在计算阶段开始之前。
②在构造函数初始化列表中没有显示提及的每个成员, 使用与初始化变量相同的规则来进行初始化。 运行该类型的默认构造函数,来初始化类类型的数据成员。
③内置或复合类型的成员的初始值依赖于对象的作用域:在局部作用域中这些成员不被初始化,而在全局作用域中,它们被初始化为0。
④计算阶段由构造函数体内的所有语句构成。在计算阶段中,数据成员的设置被认为是赋值,而不是初始化。没有清楚地认识到这个区别是程序错误和低效的常见源泉。
⑤. 初始化 != 赋值.;初始化代表为变量分配内存. 变量在其定义处被编译器初始化(编译时). 在函数中, 函数参数初始化发生在函数调用时(运行时).,赋值代表"擦除对象当前值, 赋予新值". 它不承担为对象分配内存的义务.
结论:构造函数初始化列表是对类的成员做初始化,而在构造函数体内只是对类的数据成员进行了一次赋值操作。
1. 初始化列表存在的价值:
首先把数据成员按类型分类并分情况说明:
①.内置数据类型,复合类型(指针,引用)
在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的
②.用户定义类型(类类型)
结果上相同,但是性能上存在很大的差别。更受欢迎的实现是用成员初始化表:因为类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)
2. 那么什么时候需要构造函数初始化列表呢?
(1) const成员
(2) 引用类型成员
(3) 继承类中调用基类初始化构造函数, 实际上就是先构造基类对象, 必须使用初始化列表.
以上3种情况需要在构造函数初始化列表中对数据成员进行显式初始化。因为const和引用类型成员只能初始化,不能对其进行赋值操作。
事实上我们应该尽量使用初始化列表,而不要在构造函数里赋值
3. 初始化顺序
构造函数初始化列表只是指定了成员的初始值,并没有指定初始化顺序,那么成员初始化顺序又是怎样的呢?成员的初始化顺序就是定义成员的顺序,第一个定义的成员首先被初始化,然后是第二个等等。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:cc++
原文地址:http://blog.csdn.net/meetings/article/details/47037305