c++ 为什么用初始化列表的方式构造对象效率更高

如果一个类二使用类一中的内容进行初始化,那么使用初始化列表的方式会更快。如果只是普通的数据类型没有区别,但是如果是自己定义的数据类型就会更快,因为初始化列表的方式会减少一次默认构造函数的调用。
在进入构造函数体之前,使用初始化列表,不用调用默认构造函数,进入函数体后,在进行赋值初始化,需要调用默认构造函数,再进行一次赋值。

下面两段代码:

1
2
3
4
5
6
7
8
9
// (1)
class classA {...};
class classB
{
public:
classB(classA a) {mA = a;}
private:
classA mA;
};
1
2
3
4
5
6
7
8
9
// (2)
class classA {...};
class classB
{
public:
classB(classA a): mA(a) {}
private:
classA mA;
};

2比1会快。

首先把数据成员按类型分类

  1. 内置数据类型,复合类型(指针,引用)

  2. 用户定义类型(类类型)

分情况说明:

  • 对于类型1,在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的

  • 对于类型2,结果上相同,但是性能上存在很大的差别

初始化列表,顾名思义,是对成员数据进行初始化,而不是赋值,赋值操作在构造函数体内!

对于代码1有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#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
2
3
4
5
6
7
8
9
10
11
12
// 打印如下:
//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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 打印如下:
//1 classA()
//2 copy classA() // 形参处进行拷贝
//3 classA() // 初始化成员变量mA
//4 operator= //赋值
//5 ~classA()
//6 ~classA()
//7 ~classA()
classA a; 调用默认构造函数构造a对象
classB(classA a) classB类的构造函数里的 classA a形参拷贝1声明的对象
初始化列表进行初始化,调用mA的默认构造函数,因为初始化列表没有内容,是空的,所以直接把类中包含的成员对象进行初始化
operator=, 函数体内赋值操作,把2里的a赋值给mA
2里的形参a析构
1里的a析构
对象b里的mA析构

所以简单来说就是,如果使用初始化列表,对于成员对象mA

就像是&#x20;

1
2
classA a;
classA b = a;

如果不是初始化列表,进入了函数体,那就是

1
2
3
classA a;
classB b; //多调用的构造函数
b = a;

总结就是:

如果没有初始化列表会调用默认构造函数进行初始化,如果有初始化列表,就直接拷贝构造了,所以会加速,这是对于非内置类型来说的。

对于内置类型来说,是没有区别的。