成员初始化列表作用:
第一、三点略过不讲,来直接看第二点,先上代码
1 class A 2 { 3 public: 4 A(int i = 0) :m_i(i) { cout << "A的构造函数" << endl; cout << this << endl; } 5 A(const A& a):m_i(a.m_i) { cout << "A的拷贝构造函数" << endl; cout << this << endl; } 6 A& operator=(A& a) { cout << "A的赋值函数" << endl; cout << this << endl; return *this; } 7 ~A() { cout << "A的析构函数" << endl; } 8 private: 9 int m_i; 10 }; 11 12 class B 13 { 14 public: 15 // explicit用于禁止隐式转换 explicit B(A a) 17 { 18 cout << "////////////////////" << endl; 19 cout << "a = " << &a << endl; 20 cout << "m_a = " << &m_a << endl; 21 m_a = a; 22 } 23 private: 24 A m_a; 25 }; 26 27 int main() 28 { 29 A a{5}; 30 B b{a}; 31 32 return 0; 33 }
输出结果:
这段代码很简单,就是分别创建 a 和 b 两个变量,而为了创建 b 这个变量,可以看到 A 的构造函数调用了三次,一次是创建 a ,一次是创建 m_a, 一次是 B 构造函数形参构建,为了给 m_a 赋值,还调用了一次赋值函数。
先回到正题,假如使用成员初始化列表的方式,会怎么样?
把 16 行代码改为
B(A a):m_a(a)
把 21 行删除(已经没用了),再观察一次输出结果
可以看到,少了一次赋值函数调用,以及 B 的私有变量 m_a 调用的构造函数变成了拷贝构造函数,因为
A m_a; // 调用构造函数 m_a = a; // 调用赋值函数 // 变成 A m_a = a; // 调用拷贝构造
这就能看出初始化成员列表的作用:至少可以减少一次赋值函数的调用
还是刚刚的代码,在修改过的基础上,将会产生临时变量的地方修改为引用
// 16行改为 B(A& a):m_a(a) // 第24行改为 A& m_a;
运行结果如下
可以看到只调用了一次 A 的构造函数。
总结:函数变量尽量以引用或者指针的方式接收,可以减少不必要的临时变量产生。