面试题答案
一键面试性能影响
- 对于自定义类类型成员:
- 初始化成员列表:直接调用自定义类的构造函数进行初始化,一步到位。例如,假设有一个自定义类
MyClass
,在ComplexClass
的构造函数初始化列表中初始化MyClass
成员,会直接使用MyClass
的构造函数进行初始化。 - 构造函数体内赋值:首先会调用自定义类的默认构造函数创建对象,然后再调用赋值运算符进行赋值,这涉及两次操作,性能相对较差。
- 初始化成员列表:直接调用自定义类的构造函数进行初始化,一步到位。例如,假设有一个自定义类
- 对于基本数据类型成员:
- 初始化成员列表:直接初始化,效率较高。
- 构造函数体内赋值:虽然也能完成赋值操作,但在一些编译器优化不足的情况下,可能会有轻微的性能差异,初始化列表的方式逻辑上更直接。
性能差异显著的情况
当ComplexClass
包含多个自定义类类型成员时,性能差异最为显著。因为每个自定义类类型成员在构造函数体内赋值都会经历默认构造和赋值两次操作,而使用初始化成员列表则只进行一次构造操作。随着自定义类类型成员数量的增加,这种性能差距会更加明显。
代码示例
#include <iostream>
class MyClass {
public:
MyClass(int value) : data(value) {
std::cout << "MyClass constructor with value: " << data << std::endl;
}
MyClass() : data(0) {
std::cout << "MyClass default constructor" << std::endl;
}
MyClass& operator=(const MyClass& other) {
if (this != &other) {
data = other.data;
std::cout << "MyClass assignment operator" << std::endl;
}
return *this;
}
~MyClass() {
std::cout << "MyClass destructor" << std::endl;
}
private:
int data;
};
class ComplexClass {
public:
// 使用初始化成员列表
ComplexClass(int num, MyClass obj) : basicData(num), customObj(obj) {
std::cout << "ComplexClass constructor with init list" << std::endl;
}
// 构造函数体内赋值
ComplexClass(int num, MyClass obj) {
basicData = num;
customObj = obj;
std::cout << "ComplexClass constructor with in - body assignment" << std::endl;
}
private:
int basicData;
MyClass customObj;
};
int main() {
MyClass myObj(10);
// 使用初始化成员列表构造ComplexClass对象
ComplexClass obj1(20, myObj);
// 使用构造函数体内赋值构造ComplexClass对象
ComplexClass obj2(30, myObj);
return 0;
}
在上述代码中,ComplexClass
类有一个基本数据类型成员basicData
和一个自定义类类型成员customObj
。通过对比两种构造方式,可以明显看到使用初始化成员列表在初始化customObj
时更高效,避免了先默认构造再赋值的额外操作。