C++ std::initializer_list | Brace Lists for Functions and Containers

C++ std::initializer_list | Brace Lists for Functions and Containers

이 글의 핵심

`std::initializer_list` lets functions and constructors accept `{1,2,3}` syntax. It is a small view over a temporary array—read-only, shared on copy—and interacts with narrowing rules and `vector` overloads.

What is std::initializer_list?

std::initializer_list<T> is a standard type (C++11) representing values from a brace-enclosed list {a,b,c}. It is widely used for container initialization and function parameters that want a variable number of same-type arguments.

#include <initializer_list>
#include <vector>

void print(std::initializer_list<int> list) {
    for (int x : list) {
        std::cout << x << " ";
    }
    std::cout << std::endl;
}

int main() {
    print({1, 2, 3, 4, 5});
}

Why it matters:

  • Variadic-like call sites without variadic templates
  • Type safety for homogeneous lists
  • STL integration—containers support it

Container initialization

std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2{1, 2, 3, 4, 5};

std::map<std::string, int> m = {
    {"Alice", 90},
    {"Bob", 85}
};

std::set<int> s = {1, 2, 3, 4, 5};

Custom class

class MyVector {
    std::vector<int> data;
public:
    MyVector(std::initializer_list<int> list) : data(list) {}
    void print() const {
        for (int x : data) std::cout << x << " ";
        std::cout << std::endl;
    }
};

int main() {
    MyVector v = {1, 2, 3, 4, 5};
    v.print();
}

Examples

Sum / stats

int sum(std::initializer_list<int> list) {
    int total = 0;
    for (int x : list) total += x;
    return total;
}

2D matrix helper

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

Braces vs parentheses (vector)

std::vector<int> v1{10};   // one element: 10
std::vector<int> v2(10);   // size 10

std::vector<int> v3{10, 20};  // two elements
std::vector<int> v4(10, 20);  // size 10, fill 20

Narrowing

int x = 3.14;   // allowed (warning)
// int y{3.14}; // error in list context
int y{static_cast<int>(3.14)};

Most Vexing Parse

Widget w{};   // object
// Widget w();  // function declaration

Implementation model (conceptual)

initializer_list holds begin pointer + size to a compiler-generated const array. Copying the initializer_list object is cheap and may alias the same storage.

Lifetime: the backing array lives until the end of the full-expression containing the list—do not return a initializer_list pointing at stale storage; return a vector (or similar) instead.

Patterns

Builder

class QueryBuilder {
    std::vector<std::string> conditions_;
public:
    QueryBuilder& where(std::initializer_list<std::string> conditions) {
        for (const auto& c : conditions) conditions_.push_back(c);
        return *this;
    }
};

makeSet

template<typename T>
std::set<T> makeSet(std::initializer_list<T> list) {
    return std::set<T>(list);
}

FAQ

Q1: When to use?
A: Homogeneous variable-length lists at the call site; container initialization.

Q2: Modify elements?
A: No—elements are const in the view; copy to vector to mutate.

Q3: Empty list?
A: Pass {}.

Resources: cppreference — std::initializer_list, Effective Modern C++ Item 7.

Related: List initialization, Uniform initialization.

One line: initializer_list is the standard way to pass {...} lists—a small read-only view, not a growable container.


  • C++ Uniform initialization
  • C++ List initialization
  • C++ Initializer-list constructor

Keywords

C++, initializer_list, braced initialization, C++11, STL.


  • C++ async & launch