Question

Consider the following example:

#include <cstdlib>
struct A
{
    A(int, char*){};
    A(const A&){ printf("copy-ctor\n"); }
};
int main()
{
    A x = A(5, nullptr);
}

According to 8.5.16 (of C++11 standard) the line

    A x = A(5, nullptr);

is treated as

    A x(A(5, nullptr));

(i.e. a temporary object of type A is created and passed to copy-ctor of type A to initialize an x). Then according to 12.8.31 compiler is allowed (but is not forced) to perform an optimization called "copy elision" to eliminate the creation of a temporary of type A which effectively makes that line of code to become

    A x(5, nullptr);

(i.e. no temporaries created, no copy-ctors called).

Now, suppose I use a list-initialization in the example above like this:

    A x = {5, nullptr}; // (1)

or

    A x = A{5, nullptr}; // (2)

Can someone please quote the appropriate pharagraphs from C++11 standard that confirm or deny that (1) and/or (2) would always (i.e. not only when compiler can do "copy elision" optimization) be treated as

    A x(5, nullptr);

(i.e. first constructor of A is being directly called, no temporaries created, no copying of objects of type A is performed).

Était-ce utile?

La solution

This answer is apparently wrong, which surprised me to learn. See the comments. I think the first and fourth bullet points of [dcl.init.list]/3 are what mean (1) invokes a constructor (or performs aggregate init) directly, without a temporary.

There is nothing in the standard that guarantees that (1) and (2) avoid a temporary. They are both copy-initialization, (1) is copy-list-initialization as defined by [dcl.init.list] p1:

List-initialization can occur in direct-initialization or copy-initialization contexts; list-initialization in a direct-initialization context is called direct-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization.

In both cases it is copy-initialization, and [dcl.init] says that may involve a move (which can be elided).

8.5/14,15:

The initialization that occurs in the form

T x = a;

[...] is called copy-initialization.

The initialization that occurs in the forms

T x(a);

T x{a};

[...] is called direct-initialization.

If your compiler is not smart enough to always elide the temporary, then to ensure no temporary with list-initialization you can use direct-list-initialization, i.e.

A x{5, nullptr};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top