C++类中成员变量的初始化有两种方式(二选一)
- 构造函数初始化列表
- 构造函数体内赋值
对于不同的成员变量情况,我们使用这两种初始化的情况也有不同:
内部数据类型
对于内部类型的成员变量,两种初始化方式基本上没有区别,效率上也不存在多大差异。
- 类中 const 数据成员、引用数据成员,必须在初始化列表中初始化(常量)。
class ClassName
{
public:
ClassName(int val_a, int val_b, int ref, int constVal) : // 初始化列表
Val_A(val_a),
Val_B(val_b),
Ref(ref),
ConstVal(constVal) // 常量只能用初始化列表
{
...
}
// ===================或者================================
ClassName(int val_a, int val_b) // 函数体内赋值
{
Val_A = val_a;
Val_B = val_b;
...
}
private:
int Val_A;
int Val_B;
int &Ref;
const int ConstVal;
};
没有提供默认构造函数的类的子类
class Father
{
public:
Father(int val_a, int val_b) : // 没有提供无参的constructor
Val_A(val_a),
Val_B(val_b)
{ ... }
private:
int Val_A;
int Val_B;
};
class Son : public Father
{
public:
// 子类Son初始化时,要先进行父类Father的初始化。
// 父类Father只提供了含参的constructor的情况下,子类Son要传递相应参数进行初始化,
// 且在初始化列表里进行:
Son(int val_a, int val_b, int sonVal):
Father(val_a, val_b)
{
this->SonVal = sonVal;
}
private:
int SonVal;
};
非内部(自定义)数据类型
先定义一个类:Student
class Student
{
public:
Student(int id = 0) // 构造函数
{
cout << "Student Constructor Called" << std::endl;
ID = id;
}
Student(Student & other) // 拷贝构造函数
{
cout << "Student Copy Construct Called" << std::endl;
ID = other.ID;
}
Student & operator = (Student & other) // 重载赋值=
{
cout << "Student Operator = Called" << std::endl;
ID = other.ID;
return *this;
}
private:
int ID;
};
然后我们看看如果另一个类 Deskmate(非继承关系)中,要初始化 Student 对象的情况:
-
初始化列表
class Deskmate { public: Deskmate(Student & studentA, Student & studentB) : Student_A(studentA), Student_B(studentB) // 列表初始化 { cout << "Deskmate Constructor Called" << std::endl; } private: Student Student_A; Student Student_B; };
-
赋值
class Deskmate { public: Deskmate(Student & studentA, Student & studentB) { cout << "Deskmate Constructor Called" << std::endl; Student_A = studentA; // 赋值初始化 Student_B = studentB; } private: Student Student_A; Student Student_B; };
主函数声明与输出结果:
int main()
{
Student s1(1), s2(2);
Deskmate d(s1,s2);
return 0;
}
- O: 初始化列表
- Student Constructor Called
- Student Constructor Called
- Student Copy Constructor Called
- Student Copy Constructor Called
- Deskmate Constructor Called
- O: 赋值初始化
- Student Constructor Called
- Student Constructor Called
- Student Constructor Called
- Student Constructor Called
- Deskmate Constructor Called
- Student Operator = Called
- Student Operator = Called
即使是将 Student 类对象按引用传入,在初始化时仍需要再为 Student_A, Student_B 调用构造函数(如果按值传入,就还要多调用两次复制构造函数)。用列表初始化时直接调用了 复制构造函数;而赋值初始化需要先调用 普通的构造函数,再使用重载的赋值运算符。
因此我们有结论:对于非内部类型的成员变量,列表初始化方式效率更高。
Reference
《C++ Primer(第5版)》
https://www.cnblogs.com/vivian187/p/12736988.html