Стандарт C++ 11 (1119564), страница 63
Текст из файла (страница 63)
[ Example:int g(int);void f() {int i;int& r = i;r = 1;int* p = &r;int& rr = r;int (&rg)(int) = g;rg(i);int a[3];int (&ra)[3] = a;ra[1] = i;}////////////r refers to ithe value of i becomes 1p points to irr refers to what r refers to, that is, to irg refers to the function gcalls function g// ra refers to the array a// modifies a[1]— end example ]2A reference cannot be changed to refer to another object after initialization. Note that initialization of areference is treated very differently from assignment to it. Argument passing (5.2.2) and function valuereturn (6.6.3) are initializations.3The initializer can be omitted for a reference only in a parameter declaration (8.3.5), in the declaration ofa function return type, in the declaration of a class member within its class definition (9.2), and where theextern specifier is explicitly used.
[ Example:int& r1;extern int& r2;// error: initializer missing// OK— end example ]4Given types “cv1 T1” and “cv2 T2,” “cv1 T1” is reference-related to “cv2 T2” if T1 is the same type as T2, orT1 is a base class of T2. “cv1 T1” is reference-compatible with “cv2 T2” if T1 is reference-related to T2 and cv1is the same cv-qualification as, or greater cv-qualification than, cv2.
For purposes of overload resolution,cases for which cv1 is greater cv-qualification than cv2 are identified as reference-compatible with addedqualification (see 13.3.3.2). In all cases where the reference-related or reference-compatible relationship oftwo types is used to establish the validity of a reference binding, and T1 is a base class of T2, a programthat necessitates such a binding is ill-formed if T1 is an inaccessible (Clause 11) or ambiguous (10.2) baseclass of T2.5A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:— If the reference is an lvalue reference and the initializer expression— is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2,” or— has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can beimplicitly converted to an lvalue of type “cv3 T3,” where “cv1 T1” is reference-compatible with “cv3T3”106 (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6)and choosing the best one through overload resolution (13.3)),106) This requires a conversion function (12.3.2) returning a reference type.§ 8.5.3© ISO/IEC 2011 – All rights reserved209ISO/IEC 14882:2011(E)then the reference is bound to the initializer expression lvalue in the first case and to the lvalue resultof the conversion in the second case (or, in either case, to the appropriate base class subobject ofthe object).
[ Note: The usual lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer(4.3) standard conversions are not needed, and therefore are suppressed, when such direct bindings tolvalues are done. — end note ][ Example:double d = 2.0;double& rd = d;const double& rcd = d;// rd refers to d// rcd refers to dstruct A { };struct B : A { operator int&(); } b;A& ra = b;// ra refers to A subobject in bconst A& rca = b;// rca refers to A subobject in bint& ir = B();// ir refers to the result of B::operator int&— end example ]— Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall beconst), or the reference shall be an rvalue reference.
[ Example:double& rd2 = 2.0;int i = 2;double& rd3 = i;// error: not an lvalue and reference not const// error: type mismatch and reference not const— end example ]— If the initializer expression— is an xvalue, class prvalue, array prvalue or function lvalue and “cv1 T1” is referencecompatible with “cv2 T2”, or— has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can beimplicitly converted to an xvalue, class prvalue, or function lvalue of type “cv3 T3”, where“cv1 T1” is reference-compatible with “cv3 T3”,then the reference is bound to the value of the initializer expression in the first case and tothe result of the conversion in the second case (or, in either case, to an appropriate base classsubobject).
In the second case, if the reference is an rvalue reference and the second standard conversion sequence of the user-defined conversion sequence includes an lvalue-to-rvalue conversion,the program is ill-formed.[ Example:struct A { };struct B : A { } b;extern B f();const A& rca2 = f();A&& rra = f();struct X {operator B();operator int&();} x;const A& r = x;int i2 = 42;int&& rri = static_cast<int&&>(i2);// bound to the A subobject of the B rvalue.// same as above// bound to the A subobject of the result of the conversion// bound directly to i2§ 8.5.3210© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)// bound directly to the result of operator B// error: lvalue-to-rvalue conversion applied to the// result of operator int&B&& rrb = x;int&& rri2 = X();— end example ]— Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expressionusing the rules for a non-reference copy-initialization (8.5).
The reference is then bound to thetemporary. If T1 is reference-related to T2, cv1 shall be the same cv-qualification as, or greatercv-qualification than, cv2. If T1 is reference-related to T2 and the reference is an rvalue reference,the initializer expression shall not be an lvalue. [ Example:const double& rcd2 = 2;double&& rrd = 2;const volatile int cvi = 1;const int& r2 = cvi;double d2 = 1.0;double&& rrd2 = d2;int i3 = 2;double&& rrd3 = i3;// rcd2 refers to temporary with value 2.0// rrd refers to temporary with value 2.0// error: type qualifiers dropped// error: copying lvalue of related type// rrd3 refers to temporary with value 2.0— end example ]In all cases except the last (i.e., creating and initializing a temporary from the initializer expression), thereference is said to bind directly to the initializer expression.6[ Note: 12.2 describes the lifetime of temporaries bound to references.
— end note ]8.5.41List-initialization[dcl.init.list]List-initialization is initialization of an object or reference from a braced-init-list. Such an initializer iscalled an initializer list, and the comma-separated initializer-clauses of the list are called the elements of theinitializer list. An initializer list may be empty. List-initialization can occur in direct-initialization or copyinitialization contexts; list-initialization in a direct-initialization context is called direct-list-initialization andlist-initialization in a copy-initialization context is called copy-list-initialization.
[ Note: List-initializationcan be used— as the initializer in a variable definition (8.5)— as the initializer in a new expression (5.3.4)— in a return statement (6.6.3)— as a function argument (5.2.2)— as a subscript (5.2.1)— as an argument to a constructor invocation (8.5, 5.2.3)— as an initializer for a non-static data member (9.2)— in a mem-initializer (12.6.2)— on the right-hand side of an assignment (5.17)[ Example:§ 8.5.4© ISO/IEC 2011 – All rights reserved211ISO/IEC 14882:2011(E)int a = {1};std::complex<double> z{1,2};new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elementsf( {"Nicholas","Annemarie"} ); // pass list of two elementsreturn { "Norah" };// return list of one elementint* e {};// initialization to zero / null pointerx = double{1};// explicitly construct a doublestd::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} };— end example ] — end note ]2A constructor is an initializer-list constructor if its first parameter is of type std::initializer_list<E>or reference to possibly cv-qualified std::initializer_list<E> for some type E, and either there areno other parameters or else all other parameters have default arguments (8.3.6).
[ Note: Initializer-listconstructors are favored over other constructors in list-initialization (13.3.1.7). — end note ] The templatestd::initializer_list is not predefined; if the header <initializer_list> is not included prior to a useof std::initializer_list — even an implicit use in which the type is not named (7.1.6.4) — the programis ill-formed.3List-initialization of an object or reference of type T is defined as follows:— If the initializer list has no elements and T is a class type with a default constructor, the object isvalue-initialized.— Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1).[ Example:double ad[] = { 1, 2.0 };int ai[] = { 1, 2.0 };// OK// error: narrowingstruct S2 {int m1;double m2, m3;};S2 s21 = { 1, 2, 3.0 };S2 s22 { 1.0, 2, 3 };S2 s23 { };// OK// error: narrowing// OK: default to 0,0,0— end example ]— Otherwise, if T is a specialization of std::initializer_list<E>, an initializer_list object isconstructed as described below and used to initialize the object according to the rules for initializationof an object from a class of the same type (8.5).— Otherwise, if T is a class type, constructors are considered.
The applicable constructors are enumeratedand the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (seebelow) is required to convert any of the arguments, the program is ill-formed.[ Example:struct S {S(std::initializer_list<double>);S(std::initializer_list<int>);S();// ...};S s1 = { 1.0, 2.0, 3.0 };// #1// #2// #3// invoke #1§ 8.5.4212© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)S s2 = { 1, 2, 3 };S s3 = { };// invoke #2// invoke #3— end example ][ Example:struct Map {Map(std::initializer_list<std::pair<std::string,int>>);};Map ship = {{"Sophie",14}, {"Surprise",28}};— end example ][ Example:struct S {// no initializer-list constructorsS(int, double, double);S();// ...};S s1 = { 1, 2, 3.0 };S s2 { 1.0, 2, 3 };S s3 { };// #1// #2// OK: invoke #1// error: narrowing// OK: invoke #2— end example ]— 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.