查看下面两段代码:
// (1)
class classA {...};
class classB
{
public:
classB(classA a) {mA = a;}
private:
classA mA;
};
// (2)
class classA {...};
class classB
{
public:
classB(classA a): mA(a) {}
private:
classA mA;
};
为什么2的效率要高?
初始化列表的效率要高。
首先把数据成员按类型分类
- 内置数据类型,复合类型(指针,引用)
- 用户定义类型(类类型)
分情况说明:
- 对于类型1,在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的
- 对于类型2,结果上相同,但是性能上存在很大的差别
初始化列表,顾名思义,是对成员数据进行初始化,而不是赋值,赋值操作在构造函数体内!
好比:
classA a;
classA b = a;
和
classA a;
classA b;
b = a;
的区别。
上述的代码1不够清晰,我们写成下面这样:
#include <iostream>
using namespace std;
class classA {
public:
classA() { cout << "classA()" << endl; }
classA(const classA& a) { cout << "copy classA()" << endl; }
~classA() { cout << "~classA()" << endl; }
classA& operator=(const classA& a) {
cout << "operator=" << endl;
return *this;
}
};
class classB
{
public:
classB(classA a) : mA(a) {}
private:
classA mA;
};
int main()
{
classA a;
classB b(a);
}
// 打印如下:
//1 classA()
//2 copy classA()
//3 copy classA()
//4 ~classA()
//5 ~classA()
//6 ~classA()
-
classA a;
调用默认构造函数构造a对象 -
classB(classA a) : mA(a) {}
, classB类的构造函数里的classA a
形参拷贝1声明的对象 -
classB(classA a) : mA(a) {}
, 初始化列表拷贝2里的形参a的对象 - 2里的形参a析构
- 1里的a析构
- 对象b里的mA析构
4,5,6的析构顺序没有验证。
对于代码2
#include <iostream>
using namespace std;
class classA {
public:
classA() { cout << "classA()" << endl; }
classA(const classA& a) { cout << "copy classA()" << endl; }
~classA() { cout << "~classA()" << endl; }
classA& operator=(const classA& a) {
cout << "operator=" << endl;
return *this;
}
};
class classB
{
public:
classB(classA a) { mA = a; }
private:
classA mA;
};
int main()
{
classA a;
classB b(a);
}
// 打印如下:
//1 classA()
//2 copy classA()
//3 classA()
//4 operator=
//5 ~classA()
//6 ~classA()
//7 ~classA()
-
classA a;
调用默认构造函数构造a对象 -
classB(classA a) : mA(a) {}
, classB类的构造函数里的classA a
形参拷贝1声明的对象 - 初始化列表进行初始化,调用默认构造函数
-
operator=
, 函数体内赋值操作,把2里的a赋值给mA - 2里的形参a析构
- 1里的a析构
- 对象b里的mA析构
代码2相对于代码1,少了一次默认的构造函数。 代码1直接调用拷贝构造,代码2先调用默认构造,再调用赋值函数。
所有初始化列表要快一点!