1. 初始化列表深度解析
初始化列表是C++类构造函数中用于成员变量初始化的关键机制。与在构造函数体内赋值不同,初始化列表直接在对象创建时完成初始化,这对于某些特殊类型的成员变量至关重要。
1.1 必须使用初始化列表的三种情况
在以下场景中,成员变量必须在初始化列表中进行初始化:
- const成员变量:const修饰的变量必须在创建时初始化
- 引用类型成员:引用必须在声明时绑定到某个对象
- 没有默认构造函数的类类型成员:当类成员没有无参构造函数时
cpp复制class CriticalMembers {
public:
CriticalMembers(int val, std::string& str, AnotherClass obj)
: const_member(val), // const成员
ref_member(str), // 引用成员
no_default_obj(obj) // 无默认构造的类成员
{}
private:
const int const_member;
std::string& ref_member;
AnotherClass no_default_obj; // 假设AnotherClass没有无参构造函数
};
1.2 初始化列表的底层原理
初始化列表的工作时机早于构造函数体执行,它直接参与对象的内存分配和初始化过程。编译器处理初始化列表的步骤如下:
- 分配对象内存空间
- 按照成员声明顺序(非初始化列表顺序)调用各成员的初始化器
- 执行构造函数体内的代码
这种机制解释了为什么const成员和引用成员必须在初始化列表中初始化——因为在进入构造函数体时,这些成员必须已经处于有效状态。
1.3 悬垂引用问题详解
悬垂引用是引用初始化时的常见陷阱,特别容易出现在以下场景:
cpp复制class DanglingRefExample {
public:
DanglingRefExample(int value)
: ref(value) // 危险!value是临时参数
{}
pri
