C++列表初始化的常见用法
C++提供了一种更安全、更统一的初始化方法,尤其在初始化容器和防止类型窄化方面非常有用。
什么是列表初始化
将 std::initializer_list
作为形参的构造函数是一种特殊的构造函数,能让一个类直接从花括号 {}
列表(即列表初始化)中创建对象。
简单来说,它的工作流程是:
- 编译器看到代码
ClassName obj = {a, b, c};
。 - 它会创建一个临时的、轻量级的
std::initializer_list
对象来包裹{a, b, c}
。 - 然后,它会寻找并调用
ClassName
中那个以std::initializer_list
为参数的构造函数。
示例:std::vector
的工作原理
你看似写的是:
1 | std::vector<int> v = {1, 2, 3}; |
实际上,编译器为你调用了 std::vector
的 std::initializer_list
构造函数,其声明类似:
1 | namespace std { |
编译器将 {1, 2, 3}
转换成一个 std::initializer_list<int>
对象,然后传递给这个构造函数。构造函数内部会遍历这个列表,并将元素添加到 vector
中。
如何为自己的类创建它
你也可以为自己的类定义这种构造函数,让它支持 {}
初始化。
1 |
|
总结:std::initializer_list
构造函数是 C++11 引入的一个桥梁,它让 {}
这种简洁直观的语法能够被用于初始化任意支持它的类对象,尤其是标准库容器。
列表初始化的常见用法
-
初始化标准库容器 (最常用)
使用std::initializer_list
构造函数,可以简洁地初始化容器。1
2
3
4
5
6
7
8
9
std::vector<int> v = {1, 2, 3, 4, 5};
std::map<std::string, int> capitals = {
{"France", "Paris"},
{"Japan", "Tokyo"}
}; -
初始化聚合类型 (struct/class/array)
这是初始化普通 C 结构体或数组最直接的方式。1
2
3
4
5
6
7struct Point {
int x;
int y;
};
Point p = {10, 20}; // 初始化 p.x=10, p.y=20
int arr[] = {1, 2, 3}; -
防止窄化转换 (提高代码安全性)
列表初始化不允许可能导致数据丢失的“窄化转换”,会在编译时报错。1
2
3double d = 3.14;
// int i = d; // 编译通过 (有警告),i 的值为 3
int j = {d}; // 编译错误!阻止了从 double 到 int 的窄化 -
在构造函数中初始化成员
在类的构造函数初始化列表中,统一使用{}
风格。1
2
3
4
5
6class MyClass {
public:
MyClass(int val) : member{val} {} // 使用 {} 初始化成员
private:
int member;
};
总而言之,它提供了一种更安全、更统一的初始化方法,尤其在初始化容器和防止类型窄化方面非常有用。