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.
Related posts
- C++ Uniform initialization
- C++ List initialization
- C++ Initializer-list constructor
Keywords
C++, initializer_list, braced initialization, C++11, STL.
More links
- C++ async & launch