12 Special member functions [special]

12.8 Copying and moving class objects [class.copy]

12.8.1 Copy/move constructors [class.copy.ctor]

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]). [ Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.

struct X {
  X(int);
  X(const X&, int = 1);
};
X a(1);             // calls X(int);
X b(a, 0);          // calls X(const X&, int);
X c = b;            // calls X(const X&, int);

 — end example ]

A non-template constructor for class X is a move constructor if its first parameter is of type X&&, const X&&, volatile X&&, or const volatile X&&, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]). [ Example: Y::Y(Y&&) is a move constructor.

struct Y {
  Y(const Y&);
  Y(Y&&);
};
extern Y f(int);
Y d(f(1));          // calls Y(Y&&)
Y e = d;            // calls Y(const Y&)

 — end example ]

Note: All forms of copy/move constructor may be declared for a class. [ Example:

struct X {
  X(const X&);
  X(X&);            // OK
  X(X&&);
  X(const X&&);     // OK, but possibly not sensible
};

 — end example ]  — end note ]

Note: If a class X only has a copy constructor with a parameter of type X&, an initializer of type const X or volatile X cannot initialize an object of type (possibly cv-qualified) X. [ Example:

struct X {
  X();              // default constructor
  X(X&);            // copy constructor with a non-const parameter
};
const X cx;
X x = cx;           // error: X::X(X&) cannot copy cx into x

 — end example ]  — end note ]

A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-qualified) X and either there are no other parameters or else all other parameters have default arguments. A member function template is never instantiated to produce such a constructor signature. [ Example:

struct S {
  template<typename T> S(T);
  S();
};

S g;

void h() {
  S a(g);           // does not instantiate the member template to produce S::S<S>(S);
                    // uses the implicitly declared copy constructor
}

 — end example ]

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted ([dcl.fct.def]). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

The implicitly-declared copy constructor for a class X will have the form

X::X(const X&)

if each potentially constructed subobject of a class type M (or array thereof) has a copy constructor whose first parameter is of type const M& or const volatile M&.119 Otherwise, the implicitly-declared copy constructor will have the form

X::X(X&)

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,

  • X does not have a user-declared copy assignment operator,

  • X does not have a user-declared move assignment operator, and

  • X does not have a user-declared destructor.

Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor.  — end note ]

The implicitly-declared move constructor for class X will have the form

X::X(X&&)

An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted ([dcl.fct.def.delete]) if X has:

  • a variant member with a non-trivial corresponding constructor and X is a union-like class,

  • a potentially constructed subobject type M (or array thereof) that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,

  • any potentially constructed subobject of a type with a destructor that is deleted or inaccessible from the defaulted constructor, or,

  • for the copy constructor, a non-static data member of rvalue reference type.

A defaulted move constructor that is defined as deleted is ignored by overload resolution ([over.match], [over.over]). [ Note: A deleted move constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead.  — end note ]

A copy/move constructor for class X is trivial if it is not user-provided and if:

  • class X has no virtual functions ([class.virtual]) and no virtual base classes ([class.mi]), and

  • the constructor 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 constructor selected to copy/move that member is trivial;

otherwise the copy/move constructor is non-trivial.

A copy/move constructor that is defaulted and not defined as deleted is implicitly defined if it is odr-used ([basic.def.odr]) or when it is explicitly defaulted after its first declaration. [ Note: The copy/move constructor is implicitly defined even if the implementation elided its odr-use ([basic.def.odr], [class.temporary]).  — end note ] If the implicitly-defined constructor would satisfy the requirements of a constexpr constructor ([dcl.constexpr]), the implicitly-defined constructor is constexpr.

Before the defaulted copy/move constructor for a class is implicitly defined, all non-user-provided copy/move constructors for its potentially constructed subobjects shall have been implicitly defined. [ Note: An implicitly-declared copy/move constructor has an implied exception specification ([except.spec]).  — end note ]

The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members. [ Note: Default member initializers of non-static data members are ignored. See also the example in [class.base.init].  — end note ] The order of initialization is the same as the order of initialization of bases and members in a user-defined constructor (see [class.base.init]). Let x be either the parameter of the constructor or, for the move constructor, an xvalue referring to the parameter. Each base or non-static data member is copied/moved in the manner appropriate to its type:

  • if the member is an array, each element is direct-initialized with the corresponding subobject of x;

  • if a member m has rvalue reference type T&&, it is direct-initialized with static_cast<T&&>(x.m);

  • otherwise, the base or member is direct-initialized with the corresponding base or member of x.

Virtual base class subobjects shall be initialized only once by the implicitly-defined copy/move constructor (see [class.base.init]).

The implicitly-defined copy/move constructor for a union X copies the object representation ([basic.types]) of X.

This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue; see [diff.special].