Initializer Lists in C++ – std::initializer_list

Filed Under: C++
Initializer Lists Cpp

In this article, we’ll take a look at using initializer lists in C++ (std::initializer_list).

Whenever you implement your own Class, you probably want a way to initialize objects directly, using a list type format (using {}).

Initializer Lists can achieve this and make your life a bit easier.

NOTE: This is not to be confused with another topic, called as Member Initializer Lists


Understanding Initializer Lists

An initializer list is a Class, which is defined in the <initializer_list.h> header file. To use this, we must include this header file.

This is also a template class, so we can pass any type to it, as a template parameter.

template <class Type>
class initializer_list

Here, Type is the template parameter that we pass to the class.

This class is also defined under the namespace std (the standard namespace). So, the full canonical path of this class will be: std::initializer_list.

Let’s look at some simple examples using std::initializer_list.

To declare an object of this type, we can initialize using the{} notation and use the auto keyword for automatic type inference.

#include <iostream>
#include <string>
#include <initializer_list>

int main() {
    // Declare an object of initializer_list
    auto init_list = { 1, 2, 3, 4, 5 };

    // Using std::string as a template argument for the initializer list
    std::initializer_list<std::string> il = { "Hello", "from", "JournalDev" };

    return 0;
}

Here, we’ve created two objects of the std::initializer_list<> type.

The template argument of the first object is automatically derived using auto, while we explicitly mention it in the second one, since we don’t use auto.

Why do we want to use initializer lists?

The advantage of these lists is that you can iterate through it, using the list.begin(), list.end(), and list.size() methods, so it is similar to a vector.

The list of methods is shown in a sample screenshot of the initializer_list.h file on Linux.

Initializer List Header
Initializer List Header
Method NameWhat does it do?
initializer_list.size()Returns the size of the list (Similar to vector.size())
initializer_list.begin()Returns an iterator to the first element of the list (Similar to vector.begin())
initializer_list.end()Returns an iterator to an element after the last element of the list (Similar to vector.end())

As you can see, it has methods like size(), begin() and end(), which are necessary for iterating through the list.

To see how this works in action, we need to create a class, and pass this initializer list to it’s constructor.

#include <iostream>
#include <initializer_list>

template <typename T>
class MyClass {
    public:
        MyClass(std::initializer_list<T> init_list) {
            // We can iterate through the initializer list
            for (auto it = init_list.begin(); it != init_list.end(); ++it) std::cout << *it << std::endl;
        }
};

This class must also be a template class, since the initializer list takes template arguments.

So let’s call our template class MyClass.

template <typename T>
class MyClass {
    public:
        int value;
        // Default constructor
        MyClass() { std::cout << "Default constructor\n"; value = -1; }
        
        // Parametrized constructor
        MyClass(int b = 100) { std::cout << "Parametrized constructor\n"; value = b; }

        // Constructor using std::initializer_list
        MyClass(std::initializer_list<T> init_list) {
            std::cout << "Initializer List Constructor\n";
            std::cout << "Iterating through the initializer_list<>\n";
            for (auto it = init_list.begin(); it != init_list.end(); ++it) {
                std::cout << "Current element in list = " << *it << std::endl;
            }
            // Set value = 20;
            value = 20;
        }
};

This takes in a template argument T, and sets value to specific values depending on the constructor called.

To use initializer lists, we must create a constructor with std::initializer_list<T> as an argument. We can then iterate through this list and assign it to objects.

For the sake of this article, we’ll simply print the items of the list.

Let’s see the complete program now.

#include <iostream>
#include <string>
#include <initializer_list>

template <typename T>
class MyClass {
    public:
        int value;
        // Default constructor
        MyClass() { std::cout << "Default constructor\n"; value = -1; }
        
        // Parametrized constructor
        MyClass(int b = 100) { std::cout << "Parametrized constructor\n"; value = b; }

        // Constructor using std::initializer_list
        MyClass(std::initializer_list<T> init_list) {
            std::cout << "Initializer List Constructor\n";
            std::cout << "Iterating through the initializer_list<>\n";
            for (auto it = init_list.begin(); it != init_list.end(); ++it) {
                std::cout << "Current element in list = " << *it << std::endl;
            }
            // Set value = 20;
            value = 20;
        }
};

int main() {
    // Declare an object of initializer_list
    auto init_list = { 1, 2, 3, 4, 5 };

    // Using std::string as a template argument for the initializer list
    std::initializer_list<std::string> il = { "Hello", "from", "JournalDev" };

    MyClass<int> my_obj = MyClass<int>(500);

    // Create an instance of MyClass using initializer lists
    MyClass<std::string> my_obj_il = { il };

    std::cout << "Value of normal instance: " << my_obj.value << std::endl;

    std::cout << "Value of instance constructed using initializer_list: " << my_obj_il.value << std::endl;

    return 0;
}

Here, we construct an object using initializer_list using this call:

std::initializer_list<std::string> il = { "Hello", "from", "JournalDev" };

The initializer list constructor will be invoked at this line.

Output

Parametrized constructor
Initializer List Constructor
Iterating through the initializer_list<>
Current element in list = Hello
Current element in list = from
Current element in list = JournalDev
Value of normal instance: 500
Value of instance constructed using initializer_list: 20

Indeed, our output seems to confirm what we want! We’ve finally made use of std::initializer_list to initialize objects!


Conclusion

In this article, we learned how we can use initializer lists in C++.


References


Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages