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