面试题答案
一键面试构造函数初始化列表
- 性能:
- 对于基本数据类型,性能差异不大。因为基本数据类型在初始化列表和构造函数体内赋值,都是直接进行赋值操作。
- 对于自定义类类型,使用初始化列表效率更高。当使用初始化列表时,自定义类对象直接在其内存位置构造,只经历一次构造过程。而在构造函数体内赋值,先调用默认构造函数构造对象,然后再调用赋值运算符进行赋值,经历了构造和赋值两个过程,增加了额外开销。
- 适用场景:
- 适用于所有成员变量,特别是自定义类类型成员变量。这样可以避免不必要的默认构造和赋值操作,提高效率。
- 当成员变量是const类型或者引用类型时,必须使用初始化列表。因为const对象和引用在定义后不能再被赋值,只能在定义时初始化。
构造函数体内赋值
- 性能:
- 对于基本数据类型,与初始化列表性能相近。
- 对于自定义类类型,性能相对较差,如上述提到会经历默认构造和赋值两个过程,增加开销。
- 适用场景:
- 对于一些简单的基本数据类型成员变量,在构造函数体内赋值可能代码看起来更简洁直观。但从性能优化角度,初始化列表更好。
- 当自定义类没有默认构造函数,且需要复杂逻辑来初始化成员变量时,构造函数体内赋值可能更合适。不过这种情况下通常也可以通过在初始化列表中调用自定义构造函数来解决。
示例代码
#include <iostream>
class MyClass {
public:
int basicVar;
class InnerClass {
public:
InnerClass() { std::cout << "InnerClass default constructor" << std::endl; }
InnerClass(int val) { std::cout << "InnerClass constructor with value: " << val << std::endl; }
InnerClass(const InnerClass& other) { std::cout << "InnerClass copy constructor" << std::endl; }
InnerClass& operator=(const InnerClass& other) {
std::cout << "InnerClass assignment operator" << std::endl;
return *this;
}
};
InnerClass innerObj;
const int constVar;
int& refVar;
// 使用初始化列表
MyClass(int basic, int innerVal, int& ref) : basicVar(basic), innerObj(innerVal), constVar(10), refVar(ref) {
std::cout << "MyClass constructor with initialization list" << std::endl;
}
// 在构造函数体内赋值
MyClass(int basic, int& ref) : constVar(10), refVar(ref) {
basicVar = basic;
InnerClass temp(5);
innerObj = temp;
std::cout << "MyClass constructor with assignment in body" << std::endl;
}
};
int main() {
int num = 5;
MyClass obj1(10, 20, num);
MyClass obj2(15, num);
return 0;
}
上述代码中,MyClass
类包含基本数据类型basicVar
、自定义类类型innerObj
、const
类型constVar
和引用类型refVar
。MyClass
类有两个构造函数,一个使用初始化列表,一个在构造函数体内赋值,可以直观看到不同初始化方式的特点和区别。