C++ 构造函数中的初始化参数列表initializer list
今天我们来说说C++中的构造函数初始列表initializer list, 我们来看一个例子
class Task { private: int id; public: Task(int id) :id(id) { std::cout << "生产:" << id << std::endl; } }
看到这句 可能会有疑惑:
Task(int id) : id(id) => C#中是不能这么写的,C++里这样写是什么意思? 它在C++中叫做 构造函数初始化列表,分拆如下
含义分拆如下
| 部分 | 意义 |
|---|---|
Task(int id) |
构造函数参数 |
: |
表示接下来是初始化列表 |
id(id) |
用参数 id 初始化成员变量 id |
也就是说 => “把传进来的 id,用来初始化类里的 id 成员变量”
C++中为何可以这样写呢? =》 C++规定,成员变量在进入函数构造体之前必须先完成初始化
上面那个例子,有人会这样写
class Task { private: int id; public: Task(int id) { this -> id = id; std::cout << "生产:" << id << std::endl; } }
这样写和上面那样构造函数初始化列表有什么区别呢 => 它们看起来类似,但本质上差别很大
| 方式 | 行为 |
|---|---|
: id(id) |
✅ 直接初始化(推荐) |
this->id = id |
❌ 先默认初始化,再赋值 |
我们来看这个例子进行比较
class A { int x; public: A(int val) : x(val) {} // ✅ 直接构造 A(int val) { x = val; } // ❌ 先构造再赋值 };
上面类A中的第二个构造函数,就相当于
x = 0; // 默认初始化
x= val; // 把x默认初始化为0后,再把变量val的值赋给它
必须使用构造函数初始化列表的情况
1. const成员
class A { const int x; public: A(int val) : x(val) {} // ✅ 必须这样写 };
你不能这样写
class A { const int x; public: A(int val) { x = val; //不能这样写,因为x是const变量,不能赋值 } };
2. 引用成员
class A { int& ref; public: A(int& r) : ref(r) {} // ✅ 必须初始化 };
3. 成员是对象
class B { public: B(int x) {} }; class A { B b; public: A() : b(10) {} // ✅ 必须这样写 };
C++中的构造函数初始化列表有不少好处:
- ✅ 性能更好(少一次赋值)
- ✅ 代码更清晰
- ✅ 避免未初始化风险
- ✅ 必要场景统一风格
我们再来看一下 =》 初始化按变量声明顺序
class A { int x; int y; public: A(int a, int b) : y(b), x(a) {} };
在这个例子中,注意它是x先初始化,y后面再初始化. 因为初始化按变量声明顺序,而不是按照初始化列表顺序
浙公网安备 33010602011771号