Стандарт C++ 11 (1119564), страница 80
Текст из файла (страница 80)
A using-declaration (7.3.3) that brings in from a base class an assignment operatorwith a parameter type that could be that of a copy/move assignment operator for the derived class is notconsidered an explicit declaration of such an operator and does not suppress the implicit declaration of thederived class operator; the operator introduced by the using-declaration is hidden by the implicitly-declaredoperator in the derived class.25A copy/move assignment operator for class X is trivial if it is not user-provided and if— class X has no virtual functions (10.3) and no virtual base classes (10.1), and— the assignment operator selected to copy/move each direct base class subobject is trivial, and— for each non-static data member of X that is of class type (or array thereof), the assignment operatorselected to copy/move that member is trivial;otherwise the copy/move assignment operator is non-trivial.26A copy/move assignment operator that is defaulted and not defined as deleted is implicitly defined when itis odr-used (3.2) (e.g., when it is selected by overload resolution to assign to an object of its class type) orwhen it is explicitly defaulted after its first declaration.27Before the defaulted copy/move assignment operator for a class is implicitly defined, all non-user-providedcopy/move assignment operators for its direct base classes and its non-static data members shall havebeen implicitly defined.
[ Note: An implicitly-declared copy/move assignment operator has an exceptionspecification (15.4). — end note ]28The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy/move assignment of its subobjects. The direct base classes of X are assigned first, in the order of theirdeclaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, inthe order in which they were declared in the class definition. Let x be either the parameter of the function§ 12.8© ISO/IEC 2011 – All rights reserved283ISO/IEC 14882:2011(E)or, for the move operator, an xvalue referring to the parameter.
Each subobject is assigned in the mannerappropriate to its type:— if the subobject is of class type, as if by a call to operator= with the subobject as the object expressionand the corresponding subobject of x as a single function argument (as if by explicit qualification; thatis, ignoring any possible virtual overriding functions in more derived classes);— if the subobject is an array, each element is assigned, in the manner appropriate to the element type;— if the subobject is of scalar type, the built-in assignment operator is used.It is unspecified whether subobjects representing virtual base classes are assigned more than once by theimplicitly-defined copy assignment operator. [ Example:structstructstructstructVABC{:::};virtual V { };virtual V { };B, A { };It is unspecified whether the virtual base class subobject V is assigned twice by the implicitly-defined copyassignment operator for C.
— end example ] [ Note: This does not apply to move assignment, as a defaultedmove assignment operator is deleted if the class has virtual bases. — end note ]29The implicitly-defined copy assignment operator for a union X copies the object representation (3.9) of X.30A program is ill-formed if the copy/move constructor or the copy/move assignment operator for an object isimplicitly odr-used and the special member function is not accessible (Clause 11). [ Note: Copying/movingone object into another using the copy/move constructor or the copy/move assignment operator does notchange the layout or size of either object. — end note ]31When certain criteria are met, an implementation is allowed to omit the copy/move construction of a classobject, even if the copy/move constructor and/or destructor for the object have side effects. In such cases,the implementation treats the source and target of the omitted copy/move operation as simply two differentways of referring to the same object, and the destruction of that object occurs at the later of the timeswhen the two objects would have been destroyed without the optimization.123 This elision of copy/moveoperations, called copy elision, is permitted in the following circumstances (which may be combined toeliminate multiple copies):— in a return statement in a function with a class return type, when the expression is the name of anon-volatile automatic object (other than a function or catch-clause parameter) with the same cvunqualified type as the function return type, the copy/move operation can be omitted by constructingthe automatic object directly into the function’s return value— in a throw-expression, when the operand is the name of a non-volatile automatic object (other thana function or catch-clause parameter) whose scope does not extend beyond the end of the innermostenclosing try-block (if there is one), the copy/move operation from the operand to the exceptionobject (15.1) can be omitted by constructing the automatic object directly into the exception object— when a temporary class object that has not been bound to a reference (12.2) would be copied/movedto a class object with the same cv-unqualified type, the copy/move operation can be omitted byconstructing the temporary object directly into the target of the omitted copy/move— when the exception-declaration of an exception handler (Clause 15) declares an object of the same type(except for cv-qualification) as the exception object (15.1), the copy/move operation can be omitted123) Because only one object is destroyed instead of two, and one copy/move constructor is not executed, there is still oneobject destroyed for each one constructed.§ 12.8284© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)by treating the exception-declaration as an alias for the exception object if the meaning of the programwill be unchanged except for the execution of constructors and destructors for the object declared bythe exception-declaration.[ Example:class Thing {public:Thing();~Thing();Thing(const Thing&);};Thing f() {Thing t;return t;}Thing t2 = f();Here the criteria for elision can be combined to eliminate two calls to the copy constructor of class Thing:the copying of the local automatic object t into the temporary object for the return value of function f()and the copying of that temporary object into object t2.
Effectively, the construction of the local objectt can be viewed as directly initializing the global object t2, and that object’s destruction will occur atprogram exit. Adding a move constructor to Thing has the same effect, but it is the move construction fromthe temporary object to t2 that is elided. — end example ]32When the criteria for elision of a copy operation are met or would be met save for the fact that the sourceobject is a function parameter, and the object to be copied is designated by an lvalue, overload resolution toselect the constructor for the copy is first performed as if the object were designated by an rvalue. If overloadresolution fails, or if the type of the first parameter of the selected constructor is not an rvalue reference tothe object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as anlvalue.
[ Note: This two-stage overload resolution must be performed regardless of whether copy elision willoccur. It determines the constructor to be called if elision is not performed, and the selected constructormust be accessible even if the call is elided. — end note ][ Example:class Thing {public:Thing();~Thing();Thing(Thing&&);private:Thing(const Thing&);};Thing f(bool b) {Thing t;if (b)throw t;return t;}Thing t2 = f(false);// OK: Thing(Thing&&) used (or elided) to throw t// OK: Thing(Thing&&) used (or elided) to return t// OK: Thing(Thing&&) used (or elided) to construct t2§ 12.8© ISO/IEC 2011 – All rights reserved285ISO/IEC 14882:2011(E)— end example ]12.91Inheriting constructors[class.inhctor]A using-declaration (7.3.3) that names a constructor implicitly declares a set of inheriting constructors.
Thecandidate set of inherited constructors from the class X named in the using-declaration consists of actualconstructors and notional constructors that result from the transformation of defaulted parameters as follows:— all non-template constructors of X, and— for each non-template constructor of X that has at least one parameter with a default argument, the setof constructors that results from omitting any ellipsis parameter specification and successively omittingparameters with a default argument from the end of the parameter-type-list, and— all constructor templates of X, and— for each constructor template of X that has at least one parameter with a default argument, the set ofconstructor templates that results from omitting any ellipsis parameter specification and successivelyomitting parameters with a default argument from the end of the parameter-type-list.2The constructor characteristics of a constructor or constructor template are— the template parameter list (14.1), if any,— the parameter-type-list (8.3.5),— the exception-specification (15.4),— absence or presence of explicit (12.3.1), and— absence or presence of constexpr (7.1.5).3For each non-template constructor in the candidate set of inherited constructors other than a constructorhaving no parameters or a copy/move constructor having a single parameter, a constructor is implicitlydeclared with the same constructor characteristics unless there is a user-declared constructor with the samesignature in the class where the using-declaration appears.
Similarly, for each constructor template inthe candidate set of inherited constructors, a constructor template is implicitly declared with the sameconstructor characteristics unless there is an equivalent user-declared constructor template (14.5.6.1) in theclass where the using-declaration appears. [ Note: Default arguments are not inherited. — end note ]4A constructor so declared has the same access as the corresponding constructor in X. It is deleted if thecorresponding constructor in X is deleted (8.4).5[ Note: Default and copy/move constructors may be implicitly declared as specified in 12.1 and 12.8. — endnote ]6[ Example:struct B1 {B1(int);};struct B2 {B2(int = 13, int = 42);};struct D1 : B1 {using B1::B1;};§ 12.9286© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)struct D2 : B2 {using B2::B2;};The candidate set of inherited constructors in D1 for B1 is— B1(const B1&)— B1(B1&&)— B1(int)The set of constructors present in D1 is— D1(), implicitly-declared default constructor, ill-formed if odr-used— D1(const D1&), implicitly-declared copy constructor, not inherited— D1(D1&&), implicitly-declared move constructor, not inherited— D1(int), implicitly-declared inheriting constructorThe candidate set of inherited constructors in D2 for B2 is— B2(const B2&)— B2(B2&&)— B2(int = 13, int = 42)— B2(int = 13)— B2()The set of constructors present in D2 is— D2(), implicitly-declared default constructor, not inherited— D2(const D2&), implicitly-declared copy constructor, not inherited— D2(D2&&), implicitly-declared move constructor, not inherited— D2(int, int), implicitly-declared inheriting constructor— D2(int), implicitly-declared inheriting constructor— end example ]7[ Note: If two using-declarations declare inheriting constructors with the same signatures, the program isill-formed (9.2, 13.1), because an implicitly-declared constructor introduced by the first using-declaration isnot a user-declared constructor and thus does not preclude another declaration of a constructor with thesame signature by a subsequent using-declaration.
[ Example:struct B1 {B1(int);};struct B2 {B2(int);};struct D1 : B1, B2 {§ 12.9© ISO/IEC 2011 – All rights reserved287ISO/IEC 14882:2011(E)using B1::B1;using B2::B2;};// ill-formed: attempts to declare D1(int) twicestruct D2 : B1, B2 {using B1::B1;using B2::B2;D2(int);// OK: user declaration supersedes both implicit declarations};— end example ] — end note ]8An inheriting constructor for a class is implicitly defined when it is odr-used (3.2) to create an object of itsclass type (1.8). An implicitly-defined inheriting constructor performs the set of initializations of the classthat would be performed by a user-written inline constructor for that class with a mem-initializer-list whoseonly mem-initializer has a mem-initializer-id that names the base class denoted in the nested-name-specifierof the using-declaration and an expression-list as specified below, and where the compound-statement inits function body is empty (12.6.2).