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
Tis defined as follows:
- If
Tis an aggregate [...]- Otherwise, if the initializer list has no elements [...]
- Otherwise, if
Tis a specialization ofstd::initializer_list<E>[...]- Otherwise, if
Tis a class type [...]- Otherwise, if the initializer list has a single element of type
Eand eitherTis 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
Tis a reference type, a prvalue temporary of the type referenced byTis 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
Tis a reference type, a prvalue temporary of the type referenced byTis 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
Tis defined as follows:
- If the initializer list has no elements [...]
- Otherwise, if
Tis an aggregate [...]- Otherwise, if
Tis a specialization ofstd::initializer_list<E>[...]- Otherwise, if
Tis a class type [...]- Otherwise, if
Tis a reference to class type or ifTis any reference type and the initializer list has no elements, a prvalue temporary of the type referenced byTis 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