Skip to content

std::initializer_list

概述

std::initializer_list<T> 是 C++11 引入的轻量级容器适配器,用于让函数接受花括号初始化列表(brace-init-list)作为参数。它本身不是拥有数据的容器,而是对编译器提供的底层数组的只读视图。

典型用途包括:统一容器构造语法、实现可变参数构造函数、替代多个重载函数。

语法

cpp
#include <initializer_list>

void func(std::initializer_list<int> list);

// 构造函数中使用
class MyVector {
public:
    MyVector(std::initializer_list<int> init);
};

特性

特性说明
元素类型const T,不可修改
大小编译期确定,不可动态增减
内存布局编译器可能放在栈或只读内存区
生命周期底层数组生命周期仅限于花括号所在语句
支持的操作size()begin()end()、范围迭代

代码示例

基本用法

cpp
#include <initializer_list>
#include <vector>
#include <iostream>

class IntContainer {
    std::vector<int> data_;
public:
    IntContainer(std::initializer_list<int> init) : data_(init) {}

    void print() const {
        for (auto v : data_) std::cout << v << " ";
        std::cout << "\n";
    }
};

int main() {
    IntContainer c = {1, 2, 3, 4, 5};
    c.print();  // 1 2 3 4 5
}

作为独立函数参数

cpp
double average(std::initializer_list<double> values) {
    double sum = 0;
    for (auto v : values) sum += v;
    return values.size() > 0 ? sum / values.size() : 0.0;
}

int main() {
    std::cout << average({1.0, 2.0, 3.0, 4.0});  // 2.5
}

嵌套 initializer_list

cpp
#include <vector>
#include <initializer_list>

class Matrix {
    std::vector<std::vector<int>> data_;
public:
    Matrix(std::initializer_list<std::initializer_list<int>> rows) {
        for (auto& row : rows) {
            data_.emplace_back(row);
        }
    }
};

int main() {
    Matrix m = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
}

与构造函数重载对比

cpp
class Widget {
public:
    Widget(int a, int b) { /* 两个参数 */ }
    Widget(std::initializer_list<int> list) { /* 列表 */ }
};

Widget w1(1, 2);     // 调用 Widget(int, int)
Widget w2{1, 2};     // 调用 initializer_list 版本
Widget w3 = {1, 2};  // 调用 initializer_list 版本(优先于 (int, int))

注意事项与陷阱

空列表产生歧义

cpp
Widget w1{};     // 调用默认构造函数(C++11)
Widget w2({});   // 调用 initializer_list(空列表)

不可动态修改

initializer_list 没有 push_backinsert 等操作。它是只读视图,大小固定。

生命周期陷阱

cpp
std::initializer_list<int> get_list() {
    return {1, 2, 3};  // 危险:底层数据已超出作用域
}

initializer_list 不拥有数据。返回它时,底层数组可能已失效。实际编译器实现通常会复制,但这是未定义行为,应避免。

性能注意

对于少量元素,initializer_list 通常无额外堆分配(编译器内联到栈上)。但对于大量元素,可能有隐式拷贝开销。在性能敏感场景中,应考虑其他方案。

编译器支持

编译器最低版本
GCC4.4+
Clang3.1+
MSVC2013+(VS 12.0)

基于 MIT 许可发布