初始化列表和构造函数初始化的区别
今天在做《面试笔试宝典》的时候,遇到了初始化列表和构造函数初始化区别的问题。之前只是知道有些情况必须用初始化列表,并且初始化列表的效率要高。但是要是说两者的区别,还真是没有探究过。网上搜了一些博客,对我很有帮助,但是感觉没有讲到自己异或的地方。所以自己实践了一下。
首先,我们来把两者的一般原型给出:
初始化列表方式:
Object::Object(itn _x,int _y):x(_x),y(_y) { }
构造函数初始化:
Object::Object(int _x,int _y) { x = _x; y = _y; }
初始化列表和构造函数初始化(赋值)的方式对于内置类型的成员(如int等)来说,其实没有什么区别,其性能和结果往往一样。
但是,对于非内置类型的成员(类类型)来说,是有区别的。
我们举个栗子:
这是CMember类
#ifndef _CMEMBER_H_ #define _CMEMBER_H_ #include <iostream> using namespace std; class CMember { public: CMember() { cout << "CMember constructor 1" << endl; cmember = 0; } CMember(CMember& obj) { cout << "CMember copy constructor" << endl; } CMember(int _cmember) { cout << "CMember constructor 2" << endl; cmember = _cmember; } CMember& operator =(CMember& obj) { cout << "CMember =" << endl; return *this; } int cmember; }; #endif _CMEMBER_H_
这是MClass类
#ifndef _MCLASS_H_ #define _MCLASS_H_ #include <iostream> using namespace std; #include "CMember.h" class MClass { //MClass(CMember& _cm) :cm(_cm) //{ // //cm = _cm; //} public: MClass(CMember& _cm) //注意这里我们用的是引用,如果没有用引用,则会多一次copy构造函数的调用 { cm = _cm; } CMember cm; }; #endif _MCLASS_H_
因为编译器总是确保所有成员对象在构造函数体执行之前初始化,所以类类型的数据成员对象,在进入构造函数体之前已经完成构造。例子中编译的代码将调用CMember:: CMember()来初始化cm(这里调用一次CMember构造函数),这在控制到达赋值语句前完成。接下来有调用一个赋值运算符函数。结果是调用了两个Cstring函数(构造函数和赋值操作符)。
我们测试一下:
#include <iostream> using namespace std; #include "CMember.h" #include "MClass.h" void main() { CMember c1(1); MClass m1(c1); getchar(); }
输出如下:
下面我们试一下,初始化列表方式。
MClass(CMember& _cm) :cm(_cm)
{
}
输出:
只调用一次copy构造函数。