在这里插入图片描述
🌈个人主页:聆风吟_
🔥系列专栏: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_backerase 等方法
#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. 我们写的 {1,2,3} → 编译器生成一个临时数组

  2. initializer_list 不拷贝数组内容

  3. 它只存两个东西:

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

    • 元素大小(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++ 两种遍历方式:

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


七、特别注意

  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 构造函数,即可支持 {} 初始化

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

更多推荐