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

📅 2026/8/3 6:41:58 👁️ 阅读次数 📝 编程学习
【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_backerase等方法
#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. 我们写的{1,2,3}→ 编译器生成一个临时数组

  2. initializer_list不拷贝数组内容

  3. 它只存两个东西:

    • 指向临时数组首地址的指针

    • 元素大小(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 元素个数:3

3.5 临时对象

{1,2,3}会被编译器生成临时的 initializer_list 对象,生命周期极短,当前语句执行完即销毁。

// 严重错误:返回临时对象的引用initializer_list<int>&badFunc(){return{10,20,30};}intmain(){// 悬空引用!数据已销毁autolist=badFunc();return0;}

3.5 支持范围 for、迭代器遍历

支持现代 C++ 两种遍历方式:

  1. 范围 for(最常用)
  2. 迭代器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 40

4.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];


七、特别注意

  1. 必须添加头文件
    #include<initializer_list>
  2. 元素只读,不可修改
    for(auto&x:list){x=10;// 报错!只读属性}
  3. 仅支持同类型数据传递
    func({1,3.14,"abc"});// 报错!类型必须完全一致


📝全文总结

  1. std::initializer_list是 C++11 用于接收{}包裹的一组同类型值的模板类
  2. 核心作用:让函数/自定义类支持{}传参、初始化
  3. STL 容器(vector、map、list)的列表初始化全部依赖它
  4. 核心特性:同类型、只读、轻量、编译器自动转换
  5. 自定义类优化:添加initializer_list构造函数,即可支持{}初始化

今天的干货分享到这里就结束啦!如果觉得文章还可以的话,希望能给个三连支持一下,聆风吟的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的最大动力!