问题
Before C++11, we can do copy initialization by writing something like A a = 1; which is more or less equivalent to A a = A(1);. That is, a temporary is first created and then a copy ctor is invoked. Regardless of copy elision, this must be so conceptually and the copy ctor must be accessible.
With list initialization in C++11, we can do a copy list initialization by writing A a = {1, 2};. In my opinion, this should be more or less equivalent to A a = A(1, 2);. However, on GCC and clang, A a = {1, 2} compiles even when the copy and move ctor are inaccessible (by declaring as private). Still, A a = 1; does not compile on GCC or clang if the corresponding copy/move ctor is inaccessible. So, A a = {1, 2}; seems more or less equivalent to A a{1, 2}; which is direct list initialization. The difference between this and the real direct list initialization is that A a = {1, 2}; does not compile if the ctor that takes two ints are explicit. In this aspect, A a = {1, 2}; resembles copy initialization.
So, my question is: what is the exact semantics of expressions like A a = {1, 2}; conceptually? By conceptually, copy elision do not stay in the way.
回答1:
The standard describes it pretty well; [dcl.init.list]/3:
List-initialization of an object or reference of type
Tis defined as follows:
- [...]
- Otherwise, if
Tis a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
[over.match.list] (emphasis mine):
When objects of non-aggregate class type
Tare list-initialized (8.5.4), overload resolution selects the constructor in two phases:
Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class
Tand the argument list consists of the initializer list as a single argument.If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class
Tand the argument list consists of the elements of the initializer list.If the initializer list has no elements and T has a default constructor, the first phase is omitted.
In copy-list-initialization, if anexplicitconstructor is chosen, the initialization is ill-formed.
Hence, if no initializer-list constructor is found (as in your case), the elements of the initializer list constitute the arguments for the constructor call.
In fact, the only difference of direct-list-initialization and copy-list-initialization is covered by the last, bolded sentence.
This is one of the advantages of list-initialization: It doesn't necessitate the presence of a special member function that is not gonna be used anyway.
来源:https://stackoverflow.com/questions/26964221/does-copy-list-initialization-invoke-copy-ctor-conceptually