Search

10.9 — std::initializer_list

Consider a container in C++, say std::vector:

If we want to initialize this vector with values, we can do so directly via the initializer list syntax:

This prints:

5 4 3 2 1

In the previous lesson, we introduced the concept of container classes, and showed an example of an IntArray class that holds an array of integers:

This code won’t compile, because the IntArray class doesn’t have a constructor that knows what to do with an initializer list. As a result, we’re left initializing our array elements individually:

That’s not so great.

Class initialization using std::initializer_list

When a compiler sees an initializer list, it automatically converts it into an object of type std::initializer_list. Therefore, if we create a constructor that takes a std::initializer_list parameter, we can create objects using the initializer list as an input.

std::initializer_list lives in the <initializer_list> header.

There are a few things to know about std::initializer_list. Much like std::array or std::vector, you have to tell std::initializer_list what type of data the list holds using angled brackets, unless you initialize the std::initializer_list right away. Therefore, you’ll almost never see a plain std::initializer_list. Instead, you’ll see something like std::initializer_list<int> or std::initializer_list<std::string>.

Second, std::initializer_list has a size() function which returns the number of elements in the list. This is useful when we need to know the length of the list passed in.

Let’s take a look at updating our IntArray class with a constructor that takes a std::initializer_list. Apart from the includes and the new constructor, nothing has changed.

This produces the expected result:

5 4 3 2 1

It works! Now, let’s explore this in more detail.

Here’s our IntArray constructor that takes a std::initializer_list<value_type>, aka. std::initializer_list<int>.

On line 1: As noted above, we have to use angled brackets to denote what type of element we expect inside the list. In this case, because this is an IntArray, we’d expect the list to be filled with elements of type value_type, we use std::initializer_list<value_type>. Note that we don’t pass the list by const reference. Much like std::string_view, std::initializer_list is very lightweight and copies are cheaper than an indirection.

On line 2: We delegate allocating memory for the IntArray to the other constructor via a delegating constructor (to reduce redundant code). This other constructor needs to know the length of the array, so we pass it list.size(), which contains the number of elements in the list. We use direct initialization, rather than list initialization, because list initialization prefers list constructors.

The body of the constructor is reserved for copying the elements from the list into our IntArray class. Because IntArray has begin() and end() member functions, we can use std::ranges::copy or std::copy.

One caveat: Initializer lists will always favor a matching std::initializer_list constructor over other potentially matching constructors. Thus, this variable definition:

would match to IntArray(std::initializer_list<value_type>), not IntArray(int). If you want to match to IntArray(int) once a initializer_list constructor has been defined, you’ll need to use copy initialization or direct initialization.

Class assignment using std::initializer_list

You can also use std::initializer_list to assign new values to a class by overloading the assignment operator to take a std::initializer_list parameter. This works analogously to the above. It will allow us to do this

We’ll show an example of how to do this in the quiz solution below.

Summary

Implementing a constructor that takes a std::initializer_list parameter allows us to use list initialization with our custom classes. We can also use std::initializer_list to implement other functions that need to use an initializer list, such as an assignment operator.

Quiz time

Question #1


Using the IntArray class above, implement an overloaded assignment operator that takes an initializer list.

The following code should run:

This should print:

5 4 3 2 1 
1 3 5 7 9 11

Show Solution

%Missing lookup for lesson id 4838%

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">