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).
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};