mardi 5 mai 2015

copy list initialization vs direct list initialization of temporary

Given the following struct:

struct ABC
{
    ABC(){cout << "ABC" << endl;}
    ~ABC() noexcept {cout << "~ABC" << endl;}
    ABC(ABC const&) {cout << "copy" << endl;}
    ABC(ABC&&) noexcept {cout << "move" << endl;}
    ABC& operator=(ABC const&){cout << "copy=" << endl;}
    ABC& operator=(ABC&&) noexcept {cout << "move=" << endl;}
};

The output of:

std::pair<std::string, ABC> myPair{{}, {}};

is:

ABC
copy
~ABC
~ABC

While the output of:

std::pair<std::string, ABC> myPair{{}, ABC{}};

is:

ABC
move
~ABC
~ABC

In attempting to understand the difference between the two I think I have identified that the first case is using copy-list-initialization, while the second one uses direct-list-initialization of an unnamed temporary (numbers 7 and 2, respectively, in here: http://ift.tt/1t18ulj).

Searching for similar questions I've found this: Why does the standard differentiate between direct-list-initialization and copy-list-initialization? and this: Does copy list initialization invoke copy ctor conceptually?.

The answers in those questions discuss the fact that for copy-list-initialization, the use of an explicit constructor would render the code ill-formed. In fact, if I make ABC's default constructor explicit, my first example won't compile but that is (perhaps) a different matter.

So, the question is: Why is the temporary copied in the first case but moved in the second? What prevents it from being moved in the case of copy-list-initialization?

As a note, the following code:

std::pair<std::string, ABC> myPair = std::make_pair<string, ABC>({}, {});

Also results in a call to ABC's move constructor (and no copy constructor call), but different mechanisms may be involved.

You can try the code out (using gcc-4.9.2 in C++14 mode) at: http://ift.tt/1GMte7F

Aucun commentaire:

Enregistrer un commentaire