33 C++ STL模板库2-initializer_list

发布于:2025-08-17 ⋅ 阅读:(9) ⋅ 点赞:(0)

C++ STL模板库2-initializer_list


std::initializer_list 是 C++11 引入的特性,用于支持聚合型初始化语法(大括号初始化 {}),其核心作用是将一组值封装为临时对象,方便在函数参数或构造函数中传递可变数量的参数。
std::initializer_list适用于需要动态参数数量的场景。需注意其只读性和临时性。


一、基本概念与声明

1. 定义形式

std::initializer_list<T> 是一个模板类,内部存储指向数据的指针大小,表示一个只读序列

std::initializer_list<int> il = {1, 2, 3}; // 直接初始化

2. 生命周期

initializer_list临时对象,其生命周期与初始化表达式一致。若需长期存储,需将其内容复制到其他容器(如 std::vector)。

二、核心用法场景

1. 构造函数参数

通过 initializer_list 实现多参数构造,例如自定义容器类:

#include <iostream>
#include <vector>

class MyVector {
    
public:
    MyVector(std::initializer_list<int> list) {
        
        // 将 list 内容复制到内部存储 
        for (auto val : list) {
            data.push_back(val); 
        }
    }

    // 添加迭代器接口 
    auto begin() { return data.begin();  }
    auto end() { return data.end();  }

    

private:
    std::vector<int> data;
};

int main() {
    MyVector mv = {1, 2, 3, 4, 5};// 调用 initializer_list 构造函数 
    
    for(int& val : mv) { // 现在可以遍历 
        std::cout << val << ' ';
    }
    std::cout << std::endl;

    return 0;
}

输出结果: 1 2 3 4 5

2. 函数参数重载

与普通参数重载时,{} 优先匹配 initializer_list

#include <iostream>


void Add(int a, int b) 
{
    std::cout <<a+b<< std::endl;
}

void Add(std::initializer_list<int> list) 
{
    int sum=0;
    for(auto& v:list)
        sum +=v;
    
    std::cout <<sum<< std::endl;
}

int main() {
    
    Add(1,3);  // 调用第一个函数 
    Add({1, 2,4,5,6,7});  // 调用第二个函数 
    
    std::initializer_list<int> list={5,10,15};
    Add(list);

    return 0;
}

输出结果:
4
25
30

3. 模板函数适配

在模板中处理可变参数列表:

#include <iostream>
#include<initializer_list>

template<typename T>
    void printAll(T&& val) { 
    std::cout << val << " ";
}

template<typename T>
void printAll(std::initializer_list<T> list) {
    for (auto elem : list) {
        printAll(elem);
    }
}

int main() {

    //initializer_list的类型要保持一致
    std::initializer_list<int> list={1,2,3}; 
    list={4,5,3}; 
    printAll(list);

    std::cout<< std::endl;
    std::initializer_list<const char*> list1={"12","hello","3"}; 
    printAll(list1);

return 0;
}

输出结果:
4 5 3
12 hello 3

三、遍历与操作

1. 成员方法

  • begin() / end():获取迭代器
  • size():返回元素个数
  • size()==0:判断是否为空
for (auto it = il.begin(); it != il.end(); ++it) {
    std::cout << *it << " ";
}

2. 范围 for 循环

for (auto& val : il) {
    std::cout << val << " ";
}

[示例]:

#include <iostream>
#include<initializer_list>

//范围for的用法
template<typename T>
void printAll(std::initializer_list<T> list) 
{
    
for (auto& val : list) 
{
        std::cout << val << " ";
}
std::cout << std::endl;
}

//begin()    end()
template<typename T>
void printAll2(std::initializer_list<T> il) 
{
    for (auto it = il.begin();  it != il.end();  ++it)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

//size()
template<typename T>
void printAll3(std::initializer_list<T> il)
{
    for (size_t i = 0; i < il.size();  ++i) 
    {
        // 通过指针偏移访问 
        std::cout << il.begin()[i]  << " ";  
    }
    std::cout << std::endl;
}

int main() {

    //initializer_list的类型要保持一致
    std::initializer_list<int> list={1,2,3}; 
    std::initializer_list<const char*> list2={"12","hello","3"}; 
    
    printAll(list);// 1 2 3

    std::cout<< std::endl;
    printAll2(list2);// 12 hello 3
    printAll3(list2);// 12 hello 3

return 0;
}

四、注意事项

1. 不可修改性

initializer_list 的元素是 const 的,无法通过其迭代器修改值。

2. 避免存储引用

initializer_list 是临时对象,不能将其引用或指针长期保存:

std::initializer_list<int> il = {1, 2, 3};
auto ptr = il.begin(); // 风险:il 销毁后 ptr 成为悬垂指针 

3. 与 auto 的配合

使用 auto 推导类型时需显式指定模板参数:

auto il = {1, 2, 3}; // 错误:推导为 std::initializer_list<int>
auto il = std::initializer_list<int>{1, 2, 3}; // 正确 

五、典型应用场景

  1. 容器初始化
  2. 多维数组初始化
  3. 函数参数的灵活传递可变参数列表

网站公告

今日签到

点亮在社区的每一天
去签到