【C++11新章】一篇文章搞懂 std::initializer_list 模板类

🌈个人主页:聆风吟_
🔥系列专栏:C++11新章
🔖少年有梦不应止于心动,更要付诸行动。
文章目录
一、initializer_list 是什么?
1.1 定义
std::initializer_list 是 C++11 提供的一个模板类,专门用来接收 {} 包裹的一组同类型数据,当作函数/构造函数的参数。简单说:
-
我们写个
{1,2,3,4} -
编译器会自动把它变成
initializer_list<int> -
传给函数/构造函数使用
它就是让你的代码支持 {} 批量传值的核心工具。
1.2 必须包含的头文件
#include <initializer_list>
注意:部分编译器(如 GCC)在使用 STL 容器时会间接包含该头文件,但规范写法必须手动包含,否则可能编译失败。
1.3 标准定义简化版
template <class T>
class initializer_list
{
public:
// 迭代器
const T* begin() const noexcept;
const T* end() const noexcept;
// 元素数量
size_t size() const noexcept;
};
二、为什么需要它?
C++11 之前,给函数传一组值只能用数组、vector,写法繁琐:
void func(int arr[], int len) {} // 麻烦,需传递数组+长度
有了 initializer_list,直接用花括号列表传参,语法极简:
func({1,2,3,4}); // 简洁!直接用 {} 传一组值
STL 容器(vector、map、list)能直接 {} 初始化,全靠它!
三、核心特性
3.1 元素类型必须完全相同
std::initializer_list 只能存放同类型数据(如全int、全string),不支持 int+double+string 混合。
#include <initializer_list>
using namespace std;
void test(auto list) {}
int main()
{
// 错误:int + double + string 混合类型
test({ 10, 3.14, "hello" });
return 0;
}
3.2 只读不可修改
initializer_list 是只读视图,仅支持读取元素,不支持修改:
- 不能改值:
*it = 100 - 不能增删:无
push_back、erase等方法
#include <iostream>
#include <initializer_list>
using namespace std;
void readOnlyTest(initializer_list<int> list)
{
// 读取:完全没问题
cout << "第一个元素:" << *list.begin() << endl;
// 错误:表达式必须是可修改的左值
// list.begin() = 100;
}
int main()
{
readOnlyTest({ 1, 2, 3 });
return 0;
}
3.3 轻量级包装,不拷贝数据
这是 initializer_list 性能极高的原因:
-
我们写的
{1,2,3}→ 编译器生成一个临时数组 -
initializer_list不拷贝数组内容 -
它只存两个东西:
-
指向临时数组首地址的指针
-
元素大小(size)
-
相当于:它是数据的 “视图”,不是数据的 “副本”。
#include <iostream>
#include <initializer_list>
using namespace std;
void test(initializer_list<int> list)
{
// 拿到底层数组指针
const int* p = list.begin();
cout << "指针地址:" << p << endl;
cout << "第一个元素:" << *p << endl;
cout << "元素个数:" << list.size() << endl;
}
int main()
{
// 编译器创建临时数组 [1,2,3]
// initializer_list 只存指针 + 大小,不拷贝数据
test({1, 2, 3});
return 0;
}
输出:
指针地址:0x...
第一个元素:1
元素个数:3
3.5 临时对象
{1,2,3} 会被编译器生成临时的 initializer_list 对象,生命周期极短,当前语句执行完即销毁。
// 严重错误:返回临时对象的引用
initializer_list<int>& badFunc()
{
return {10, 20, 30};
}
int main()
{
// 悬空引用!数据已销毁
auto list = badFunc();
return 0;
}
3.5 支持范围 for、迭代器遍历
支持现代 C++ 两种遍历方式:
- 范围 for(最常用)
- 迭代器
begin()/end()
#include <iostream>
#include <initializer_list>
using namespace std;
void traverse(initializer_list<int> list)
{
cout << "--- 范围 for 遍历 ---" << endl;
for (int x : list) {
cout << x << " ";
}
cout << endl;
cout << "--- 迭代器遍历 ---" << endl;
for (auto it = list.begin(); it != list.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
traverse({10, 20, 30, 40});
return 0;
}
输出:
--- 范围 for 遍历 ---
10 20 30 40
--- 迭代器遍历 ---
10 20 30 40
四、基础用法示例
4.1 普通函数接收
#include <iostream>
// 必须包含这个头文件
#include <initializer_list>
using namespace std;
// 函数参数:接收一组 int 数据
void printNumbers(initializer_list<int> nums)
{
// 1. 获取元素个数
cout << "元素个数:" << nums.size() << endl;
// 2. 范围for遍历(最常用)
for (int num : nums)
{
cout << num << " ";
}
cout << endl;
}
int main()
{
// 直接用 {} 传一组值!
printNumbers({10, 20, 30, 40});
return 0;
}
输出:
元素个数:4
10 20 30 40
4.2 实现求和函数
int sum(initializer_list<int> nums)
{
int total = 0;
for (int n : nums)
{
total += n;
}
return total;
}
// 使用方式
sum({1,2,3}); // 结果:6
sum({10,20,30,40});// 结果:100
五、让自定义类支持 {} 初始化
给类添加参数为 initializer_list 的构造函数,即可像 vector 一样用 {} 初始化。
示例:自定义数组类,支持 {1,2,3} 初始化
#include <iostream>
#include <initializer_list>
#include <vector>
using namespace std;
class MyArray {
public:
// 关键:initializer_list 构造函数
MyArray(initializer_list<int> list)
{
// 把列表数据存入容器
for (int num : list)
{
my_data.push_back(num);
}
}
// 打印函数
void show()
{
for (int num : my_data)
{
cout << num << " ";
}
cout << endl;
}
private:
vector<int> my_data;
};
int main()
{
// 像 vector 一样使用 {} 初始化!
MyArray arr{ 1, 2, 3, 4, 5 };
arr.show(); // 输出:1 2 3 4 5
return 0;
}
六、核心成员函数
initializer_list 接口极简,仅3个核心函数:
| 函数 | 作用 |
|---|---|
begin() |
返回指向第一个元素的只读迭代器 |
end() |
返回指向最后一个元素下一位的只读迭代器 |
size() |
返回元素个数 |
常用操作:
std::initializer_list<int> list = {10,20,30};
// 获取大小
list.size();
// 访问第一个元素
*list.begin();
// 访问最后一个元素
*(list.end()-1);
// 遍历方式1:范围for(推荐)
for (int x : list) { ... }
// 遍历方式2:迭代器
for (auto it = list.begin(); it != list.end(); ++it) { ... }
// 遍历方式3:下标(不推荐,无operator[],用指针)
const int* p = list.begin();
int first = p[0];
七、特别注意
- 必须添加头文件
#include <initializer_list> - 元素只读,不可修改
for (auto& x : list) { x = 10; // 报错!只读属性 } - 仅支持同类型数据传递
func({1, 3.14, "abc"}); // 报错!类型必须完全一致
📝全文总结
std::initializer_list是 C++11 用于接收{}包裹的一组同类型值的模板类- 核心作用:让函数/自定义类支持
{}传参、初始化 - STL 容器(vector、map、list)的列表初始化全部依赖它
- 核心特性:同类型、只读、轻量、编译器自动转换
- 自定义类优化:添加
initializer_list构造函数,即可支持{}初始化
今天的干货分享到这里就结束啦!如果觉得文章还可以的话,希望能给个三连支持一下,聆风吟的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的最大动力!
更多推荐
所有评论(0)