This question pertains to this code snippet reproduced below:
struct A {
A():b(0) { }
A(const A&, int b = 0):b(b) { }
int b;
};
int main() {
A a;
const A& a1 = { a };
const A& a2 = { a, 1 };
a.b = 2;
std::cout << a1.b << a2.b << std::endl;
}
The right hand side of the assignment of a1 can be a single value in constructs or an argument list for construction. Is there anywhere in the standard that specifies which interpretation takes precedence? For a2, it is a construction of a temporary A whose address is assigned to a2, if I did not misunderstand.
BTW, compiling this code by clang++ in Coliru produced output 21. gcc++-4.8 output 01.
The definition of list-initialization has changed quite a bit since the publication of the C++11 Standard due to defect reports.
From draft n3485 (after the Standard has been published, with some corrections but without C++1y features) [dcl.init.list]/3
List-initialization of an object or reference of type
T
is defined as follows:
- If
T
is an aggregate [...]- Otherwise, if the initializer list has no elements [...]
- Otherwise, if
T
is a specialization ofstd::initializer_list<E>
[...]- Otherwise, if
T
is a class type [...]- Otherwise, if the initializer list has a single element of type
E
and eitherT
is not a reference type or its referenced type is reference-related toE
, the object or reference is initialized from that element; if a narrowing conversion is required to convert the element toT
, the program is ill-formed.- Otherwise, if
T
is a reference type, a prvalue temporary of the type referenced byT
is list-initialized, and the reference is bound to that temporary- [...]
In the latest draft from the Committee's github repo (ce016c64dc), only a slight change applies here to one point [dcl.init.list]/3:
- Otherwise, if
T
is a reference type, a prvalue temporary of the type referenced byT
is copy-list-initialized or direct-list-initialized, depending on the kind of initialization for the reference, and the reference is bound to that temporary.
From draft n3242 (before the Standard) [dcl.init.list]/3:
List-initialization of an object or reference of type
T
is defined as follows:
- If the initializer list has no elements [...]
- Otherwise, if
T
is an aggregate [...]- Otherwise, if
T
is a specialization ofstd::initializer_list<E>
[...]- Otherwise, if
T
is a class type [...]- Otherwise, if
T
is a reference to class type or ifT
is any reference type and the initializer list has no elements, a prvalue temporary of the type referenced byT
is list-initialized, and the reference is bound to that temporary.- [...]
(I don't have a copy of the Standard itself right now.)
Let's assume your compiler implements the proposed resolutions to the defect reports. Then, the first example
const A& a1 = { a };
initializes like const A& a1 = a;
(no temporary); and the second example
const A& a2 = { a, 1 };
initializes like const A& a2 = A(a,1);
.
8.5.4/3 List-initialization of an object or reference of type T is defined as follows:
...
- Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is list-initialized, and the reference is bound to that temporary.
In your example, a1
does not bind directly to a
, but to a temporary copy-constructed from a
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With