Стандарт C++ 11 (1119564), страница 74
Текст из файла (страница 74)
[ Note: The lifetime of exception objects isdescribed in 15.1. — end note ] Even when the creation of the temporary object is unevaluated (Clause 5)or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object hadbeen created and later destroyed. [ Note: even if there is no call to the destructor or copy/move constructor,all the semantic restrictions, such as accessibility (Clause 11) and whether the function is deleted (8.4.3), shallbe satisfied. However, in the special case of a function call used as the operand of a decltype-specifier (5.2.2),no temporary is introduced, so the foregoing does not apply to the prvalue of any such function call. — endnote ]2[ Example: Consider the following code:class X {public:X(int);X(const X&);X& operator=(const X&);~X();};class Y {public:Y(int);Y(Y&&);~Y();};X f(X);Y g(Y);void h() {X a(1);X b = f(X(2));Y c = g(Y(3));a = f(a);}An implementation might use a temporary in which to construct X(2) before passing it to f() using X’s copyconstructor; alternatively, X(2) might be constructed in the space used to hold the argument.
Likewise, animplementation might use a temporary in which to construct Y(3) before passing it to g() using Y’s moveconstructor; alternatively, Y(3) might be constructed in the space used to hold the argument. Also, atemporary might be used to hold the result of f(X(2)) before copying it to b using X’s copy constructor;alternatively, f()’s result might be constructed in b.
Likewise, a temporary might be used to hold the resultof g(Y(3)) before moving it to c using Y’s move constructor; alternatively, g()’s result might be constructedin c. On the other hand, the expression a=f(a) requires a temporary for the result of f(a), which is thenassigned to a. — end example ]3When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1,12.8), it shall ensure that a constructor is called for the temporary object.
Similarly, the destructor shall becalled for a temporary with a non-trivial destructor (12.4). Temporary objects are destroyed as the last stepin evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true§ 12.2260© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)even if that evaluation ends in throwing an exception. The value computations and side effects of destroyinga temporary object are associated only with the full-expression, not with any specific subexpression.4There are two contexts in which temporaries are destroyed at a different point than the end of the fullexpression.
The first context is when a default constructor is called to initialize an element of an array. Ifthe constructor has one or more default arguments, the destruction of every temporary created in a defaultargument is sequenced before the construction of the next array element, if any.5The second context is when a reference is bound to a temporary. The temporary to which the reference isbound or the temporary that is the complete object of a subobject to which the reference is bound persistsfor the lifetime of the reference except:— A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until theconstructor exits.— A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion ofthe full-expression containing the call.— The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is notextended; the temporary is destroyed at the end of the full-expression in the return statement.— A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of thefull-expression containing the new-initializer.
[ Example:struct S { int mi; const std::pair<int,int>& mp; };S a { 1, {2,3} };S* p = new S{ 1, {2,3} };// Creates dangling reference— end example ] [ Note: This may introduce a dangling reference, and implementations are encouragedto issue a warning in such a case. — end note ]The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequencedbefore the destruction of every temporary which is constructed earlier in the same full-expression. If thelifetime of two or more temporaries to which references are bound ends at the same point, these temporariesare destroyed at that point in the reverse order of the completion of their construction.
In addition, thedestruction of temporaries bound to references shall take into account the ordering of destruction of objectswith static, thread, or automatic storage duration (3.7.1, 3.7.2, 3.7.3); that is, if obj1 is an object with thesame storage duration as the temporary and created before the temporary is created the temporary shall bedestroyed before obj1 is destroyed; if obj2 is an object with the same storage duration as the temporary andcreated after the temporary is created the temporary shall be destroyed after obj2 is destroyed. [ Example:struct S {S();S(int);friend S operator+(const S&, const S&);~S();};S obj1;const S& cr = S(16)+S(23);S obj2;the expression S(16) + S(23) creates three temporaries: a first temporary T1 to hold the result of theexpression S(16), a second temporary T2 to hold the result of the expression S(23), and a third temporaryT3 to hold the result of the addition of these two expressions.
The temporary T3 is then bound to the referencecr. It is unspecified whether T1 or T2 is created first. On an implementation where T1 is created beforeT2, it is guaranteed that T2 is destroyed before T1. The temporaries T1 and T2 are bound to the reference§ 12.2© ISO/IEC 2011 – All rights reserved261ISO/IEC 14882:2011(E)parameters of operator+; these temporaries are destroyed at the end of the full-expression containing thecall to operator+. The temporary T3 bound to the reference cr is destroyed at the end of cr’s lifetime,that is, at the end of the program. In addition, the order in which T3 is destroyed takes into account thedestruction order of other objects with static storage duration. That is, because obj1 is constructed beforeT3, and T3 is constructed before obj2, it is guaranteed that obj2 is destroyed before T3, and that T3 isdestroyed before obj1.
— end example ]12.3Conversions[class.conv]1Type conversions of class objects can be specified by constructors and by conversion functions. Theseconversions are called user-defined conversions and are used for implicit type conversions (Clause 4), forinitialization (8.5), and for explicit type conversions (5.4, 5.2.9).2User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2). Conversions obey theaccess control rules (Clause 11). Access control is applied after ambiguity resolution (3.4).3[ Note: See 13.3 for a discussion of the use of conversions in function calls as well as examples below. — endnote ]4At most one user-defined conversion (constructor or conversion function) is implicitly applied to a singlevalue.[ Example:struct X {operator int();};struct Y {operator X();};Y a;int b = a;int c = X(a);// error// a.operator X().operator int() not tried// OK: a.operator X().operator int()— end example ]5User-defined conversions are used implicitly only if they are unambiguous.
A conversion function in aderived class does not hide a conversion function in a base class unless the two functions convert to the sametype. Function overload resolution (13.3.3) selects the best conversion function to perform the conversion.[ Example:struct X {operator int();};struct Y : X {operator char();};void f(Y& a) {if (a) {// ill-formed:// X::operator int() or Y::operator char()}§ 12.3262© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)}— end example ]12.3.11Conversion by constructor[class.conv.ctor]A constructor declared without the function-specifier explicit specifies a conversion from the types of itsparameters to the type of its class.
Such a constructor is called a converting constructor. [ Example:struct X {X(int);X(const char*, int =0);};void f(X arg) {X a = 1;X b = "Jessie";a = 2;f(3);}////////a = X(1)b = X("Jessie",0)a = X(2)f(X(3))— end example ]2An explicit constructor constructs objects just like non-explicit constructors, but does so only where thedirect-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used. A default constructormay be an explicit constructor; such a constructor will be used to perform default-initialization or valueinitialization (8.5). [ Example:struct Z {explicit Z();explicit Z(int);};Z a;Z a1 = 1;Z a3 = Z(1);Z a2(1);Z* p = new Z(1);Z a4 = (Z)1;Z a5 = static_cast<Z>(1);//////////////OK: default-initialization performederror: no implicit conversionOK: direct initialization syntax usedOK: direct initialization syntax usedOK: direct initialization syntax usedOK: explicit cast usedOK: explicit cast used— end example ]3A non-explicit copy/move constructor (12.8) is a converting constructor.