Having Fun With C++ [Quiz Series- Part 2]

Renana Dar
Renana Dar / Feb 24 2020
Having Fun With C++ [Quiz Series- Part 2]

Our last C++ quiz was a big success. A lot of C++ folks participated and there was one lucky winner. That’s why we decided to make it a tradition and keep the quiz juices flowing and present you with yet another C++ fun quiz!

Thanks to Anders Schau Knatten from CppQuiz for creating this quiz!

I hope you’ll find it enjoyable.

The Quiz!

#include <initializer_list>

#include <iostream>

 

class C {

public:

    C() = default;

    C(const C&) { std::cout << 1; }

};

 

void f(std::initializer_list<C> i) {}

 

int main() {

    C c;

    std::initializer_list<C> i{c};

    f(i);

    f(i);

}

Hint:

The result would be the same if we called f(i) only once.

The answer:

The program is guaranteed to output 1

Explanation:

The class C prints 1 when it’s copied. But when is it copied?

[dcl.init.list]§11.6.4¶5 in the standard explains construction of initializer_list:

An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation generated and materialized (7.4) a prvalue of type “array of N const E”, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std::initializer_list<E> object is constructed to refer to that array.

So when we construct the initializer list i, we can imagine a temporary array of one C being created, where the element is copy-initialized. Since c is an lvalue, a copy is made (not for instance a move), and 1 is printed.

Then, f is called twice, taking the freshly created initializer_list by value. So a copy of the initializer_list is made for each call. Does that make a copy of the elements in the initializer list, as it would when taking for instance a vector or a list by value? No. As we saw at the end of the quote above:

the std::initializer_list<E> object is constructed to refer to that array.

So the initializer_list only refers to that array, it doesn’t have a copy of it. A note in [initializer_list.syn]§21.9.1¶1 spells it out verbatim:

Copying an initializer list does not copy the underlying elements.

The key takeaway is: If you write an initializer list constructor for your class, never move the elements out of the initializer list. Even if you took it by value, you were not passed an exclusive copy of the elements, which might still be used by others.

Hack your C++ build times with this free guide! Download free!

Since we’ve made these quizzes a tradition, another quiz is coming soon.

 

Stay informed!

Subscribe to receive our incredibly exclusive content

Renana Dar

Renana, Incredibuild’s content marketing manager, is a data-oriented marketing professional, with over 12 years of experience in high tech, marketing, and communications. Renana specializes in building content operations from the ground up.