std::initializer_list<T> is introduced in C++11 to make initialization uniform in C++.
Before C++11 it was easy to initialize an array with with default elements like,
// Initializing array with default values int arr[]= {1,2,3,4,5};
But there was no way no to initialize other containers like vector, list and map etc.
For example, there was no way to initialize a vector with default values in a single line before c++11. The only ways was create a vector and push elements in it i.e.
// Old Way to initialize a vector std::vector<int> vec1; for(int i = 0; i < 5; i++) vec1.push_back(i);
But in C++11 we can do this in a single line i.e.
Frequently Asked:
- Using std::initializer_list in constructors to initialize member variables
- std::initializer_list Tutorial & Examples | C++11
- C++ : How to Initialize a map in one line using initialzer_list ?
// Initializing a vector using c++11 initializer_list std::vector<int> vec= {1,2,3,4,5}; // Compile Error before C++ 11
It would have resulted in a compile time error before C++11. It’s possible in C++11 because of Uniform Initialization feature of c++11 i.e. std::initializer_list<T>
std::initializer_list
We can create light weight object of std::initializer_list<T> that will refer to an array of elements of type T i.e.
std::initialzer_list<int> data = {1,2,4,5};
So, where ever compiler see elements in braces i.e. {a, b, c} it creates a std::initialzer_list<T>, where T is the type of elements in the list. Now, all containers i.e. vector & list etc. has a parameterized constructor that accepts this std::initializer_list<T> as an argument and insert them i.e.
vector<T>::vector<T>(initializer_list<T> elements) { ...... }
Therefore we can directly initialize a vector or any other container with default elements i.e.
// Initializing a vector using c++11 initializer_list std::vector<int> vec= {1,2,3,4,5}; // Compile Error before C++ 11 // Initializing a List using c++11 initializer_list std::list<int> listOfElements= {1,2,3,4,5}; // Compile Error before C++ 11
Here compiler will automatically create a object of std::initialzer_list<T> and make it refer to {1,2,3,4,5} and as vector has a constructor that accepts this as an argument. Hence it will initialize the vector with all the elements in it.
Complete Example is as follows,
#include <iostream> #include <vector> #include <list> int main() { // Initializing array with default values int arr[] = { 1, 2, 3, 4, 5 }; // Print the array for (int i = 0; i < sizeof(arr) / sizeof(int); i++) std::cout << i << " , "; std::cout << std::endl; // Old Way to initialize a vector std::vector<int> vec1; for (int i = 0; i < 5; i++) vec1.push_back(i); // Initializing a vector using c++11 initializer_list std::vector<int> vec = { 1, 2, 3, 4, 5 }; // Compile Error before C++ 11 // Initializing a List using c++11 initializer_list std::list<int> listOfElements = { 1, 2, 3, 4, 5 }; // Compile Error before C++ 11 // Print the Vector for (int i : vec) std::cout << i << " , "; std::cout << std::endl; // Print the List for (int i : listOfElements) std::cout << i << " , "; std::cout << std::endl; return 0; }
Output:
0 , 1 , 2 , 3 , 4 , 1 , 2 , 3 , 4 , 5 , 1 , 2 , 3 , 4 , 5 ,
std::initialzer_list<T> and Narrowing
std::initialzer_list<T> also detects the narrowing of data i.e. it will detect the narrowing i.e.
std::vector<int> vec= {1,2,3,4.5,5}; // Will give compile time warnings
Complete Example is as follows,
#include <iostream> #include <vector> #include <map> #include <list> int main() { // Array will not detect narrowing int arr[] { 1, 2, 3, 4.5, 5 }; for (int i = 0; i < sizeof(arr) / sizeof(int); i++) std::cout << i << " , "; std::cout << std::endl; // Initializing a vector using c++11 initializer_list // Will detect narrowing std::vector<int> vec = { 1, 2, 3, 4.5, 5 }; for (int i : vec) std::cout << i << " , "; std::cout << std::endl; return 0; }
Output:
0 , 1 , 2 , 3 , 4 , 1 , 2 , 3 , 4 , 5 ,
Lifetime of elements in std::initialzer_list<T> is till the object which refers to it.