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}; // 正确
五、典型应用场景
- 容器初始化
- 多维数组初始化
- 函数参数的灵活传递可变参数列表