310 lines
12 KiB
Markdown
310 lines
12 KiB
Markdown
[class.copy.assign]
|
||
|
||
# 11 Classes [[class]](./#class)
|
||
|
||
## 11.4 Class members [[class.mem]](class.mem#class.copy.assign)
|
||
|
||
### 11.4.6 Copy/move assignment operator [class.copy.assign]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1787)
|
||
|
||
A user-declared [*copy*](#def:copy) assignment operator X::operator= is a
|
||
non-static non-template member function of class X with exactly one
|
||
non-object parameter of type X, X&, const X&,volatile X&, or const volatile X&[.](#1.sentence-1)[90](#footnote-90 "Because a template assignment operator or an assignment operator taking an rvalue reference parameter is never a copy assignment operator, the presence of such an assignment operator does not suppress the implicit declaration of a copy assignment operator. Such assignment operators participate in overload resolution with other assignment operators, including copy assignment operators, and, if selected, will be used to assign an object.")
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
More than one form of copy assignment operator can be declared for a class[.](#1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
If a classX only has a copy assignment operator with a non-object parameter of typeX&,
|
||
an expression of type constX cannot be assigned to an object of typeX[.](#1.sentence-3)
|
||
|
||
[*Example [1](#example-1)*: struct X { X();
|
||
X& operator=(X&);};const X cx;
|
||
X x;void f() { x = cx; // error: X::operator=(X&) cannot assign cx into x} â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1835)
|
||
|
||
If the class definition does not explicitly declare a copy assignment operator,
|
||
one is declared [*implicitly*](#def:assignment_operator,copy,implicitly_declared "11.4.6 Copy/move assignment operator [class.copy.assign]")[.](#2.sentence-1)
|
||
|
||
If the class definition declares a move
|
||
constructor or move assignment operator, the implicitly declared copy
|
||
assignment operator is defined as deleted; otherwise, it is
|
||
defaulted ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions"))[.](#2.sentence-2)
|
||
|
||
The latter case is deprecated if the class has a user-declared copy constructor
|
||
or a user-declared destructor ([[depr.impldec]](depr.impldec "D.6 Implicit declaration of copy functions"))[.](#2.sentence-3)
|
||
|
||
The implicitly-declared copy assignment operator for a classX will have the formX& X::operator=(const X&) if
|
||
|
||
- [(2.1)](#2.1)
|
||
|
||
each direct base class B of X has a copy assignment operator whose non-object parameter is of typeconst B&, const volatile B&, or B, and
|
||
|
||
- [(2.2)](#2.2)
|
||
|
||
for all the non-static data members of X that are of a class type M (or array thereof),
|
||
each such class type has a copy assignment operator whose non-object parameter is of typeconst M&, const volatile M&,
|
||
or M[.](#2.sentence-4)[91](#footnote-91 "This implies that the reference parameter of the implicitly-declared copy assignment operator cannot bind to a volatile lvalue; see [diff.class].")
|
||
|
||
Otherwise, the implicitly-declared copy assignment operator
|
||
will have the formX& X::operator=(X&)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1875)
|
||
|
||
A user-declared move assignment operator X::operator= is
|
||
a non-static non-template member function of class X with exactly
|
||
one non-object parameter of type X&&, const X&&, volatile X&&, orconst volatile X&&[.](#3.sentence-1)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
More than one form of move assignment operator can be declared for a class[.](#3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1884)
|
||
|
||
If the definition of a class X does not explicitly declare a
|
||
move assignment operator, one
|
||
will be implicitly declared as defaulted if and only if
|
||
|
||
- [(4.1)](#4.1)
|
||
|
||
X does not have a user-declared copy constructor,
|
||
|
||
- [(4.2)](#4.2)
|
||
|
||
X does not have a user-declared move constructor,
|
||
|
||
- [(4.3)](#4.3)
|
||
|
||
X does not have a user-declared copy assignment operator, and
|
||
|
||
- [(4.4)](#4.4)
|
||
|
||
X does not have a user-declared destructor[.](#4.sentence-1)
|
||
|
||
[*Example [2](#example-2)*:
|
||
|
||
The class definitionstruct S {int a;
|
||
S& operator=(const S&) = default;}; will not have a default move assignment operator implicitly declared because the
|
||
copy assignment operator has been user-declared[.](#4.sentence-2)
|
||
|
||
The move assignment operator may
|
||
be explicitly defaulted[.](#4.sentence-3)
|
||
|
||
struct S {int a;
|
||
S& operator=(const S&) = default;
|
||
S& operator=(S&&) = default;}; â *end example*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1924)
|
||
|
||
The implicitly-declared move assignment operator for a class X will have the formX& X::operator=(X&&)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1930)
|
||
|
||
The implicitly-declared copy/move assignment operator for classX has the return typeX&[.](#6.sentence-1)
|
||
|
||
An implicitly-declared copy/move assignment operator is an
|
||
inline public member of its class[.](#6.sentence-2)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1938)
|
||
|
||
A defaulted copy/move assignment operator for
|
||
class X is defined as deleted if X has:
|
||
|
||
- [(7.1)](#7.1)
|
||
|
||
a non-static data member of const non-class
|
||
type (or possibly multidimensional array thereof), or
|
||
|
||
- [(7.2)](#7.2)
|
||
|
||
a non-static data member of reference type, or
|
||
|
||
- [(7.3)](#7.3)
|
||
|
||
a direct non-static data member of class type M (or possibly multidimensional array thereof) or
|
||
a direct base class M that cannot be copied/moved because overload resolution ([[over.match]](over.match "12.2 Overload resolution")),
|
||
as applied to find M's corresponding assignment operator,
|
||
either does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1 General")) or,
|
||
in the case of a variant member, selects a non-trivial function[.](#7.sentence-1)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
A defaulted move assignment operator that is defined as deleted is ignored by
|
||
overload resolution ([[over.match]](over.match "12.2 Overload resolution"), [[over.over]](over.over "12.3 Address of an overload set"))[.](#7.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1961)
|
||
|
||
Because a copy/move assignment operator is implicitly declared for a class
|
||
if not declared by the user,
|
||
a base class copy/move assignment operator is always hidden
|
||
by the corresponding assignment operator of a derived class ([[over.assign]](over.assign "12.4.3.2 Simple assignment"))[.](#8.sentence-1)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
A [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") in a derived class C that names an assignment operator from a base class
|
||
never suppresses the implicit declaration of
|
||
an assignment operator of C,
|
||
even if the base class assignment operator would be
|
||
a copy or move assignment operator
|
||
if declared as a member of C[.](#8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1978)
|
||
|
||
A copy/move assignment operator for classX is
|
||
trivial
|
||
if it is not user-provided and if
|
||
|
||
- [(9.1)](#9.1)
|
||
|
||
classX has no virtual functions ([[class.virtual]](class.virtual "11.7.3 Virtual functions"))
|
||
and no virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple base classes")), and
|
||
|
||
- [(9.2)](#9.2)
|
||
|
||
the assignment operator selected to copy/move each direct
|
||
base class subobject is trivial, and
|
||
|
||
- [(9.3)](#9.3)
|
||
|
||
for each non-static data member ofX that is of class type (or array thereof),
|
||
the assignment operator selected to copy/move that member is trivial;
|
||
|
||
otherwise the copy/move assignment operator is[*non-trivial*](#def:assignment_operator,copy,non-trivial "11.4.6 Copy/move assignment operator [class.copy.assign]")[.](#9.sentence-1)
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2006)
|
||
|
||
An implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions")) copy/move assignment operator is constexpr[.](#10.sentence-1)
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2009)
|
||
|
||
Before the defaulted copy/move assignment operator for a class is
|
||
implicitly defined,
|
||
all non-user-provided copy/move assignment operators for
|
||
its direct base classes and
|
||
its non-static data members are implicitly defined[.](#11.sentence-1)
|
||
|
||
[*Note [6](#note-6)*:
|
||
|
||
An implicitly-declared copy/move assignment operator has an
|
||
implied exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))[.](#11.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2020)
|
||
|
||
The implicitly-defined copy/move assignment operator for a
|
||
non-union class X performs memberwise copy/move assignment of its subobjects[.](#12.sentence-1)
|
||
|
||
The direct
|
||
base classes of X are assigned first, in the order of their declaration in the[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [class.derived.general]"), and then the immediate non-static data members ofX are assigned, in the order in which they were declared in the class
|
||
definition[.](#12.sentence-2)
|
||
|
||
Let x be either the parameter of the function or, for the move operator, an
|
||
xvalue referring to the parameter[.](#12.sentence-3)
|
||
|
||
Each subobject is assigned in the manner appropriate to its type:
|
||
|
||
- [(12.1)](#12.1)
|
||
|
||
if the subobject is of class type,
|
||
as if by a call to operator= with the subobject as the object expression
|
||
and the corresponding subobject of x as a single function argument
|
||
(as if by explicit qualification; that is,
|
||
ignoring any possible virtual overriding functions in more derived classes);
|
||
|
||
- [(12.2)](#12.2)
|
||
|
||
if the subobject is an array, each element is assigned,
|
||
in the manner appropriate to the element type;
|
||
|
||
- [(12.3)](#12.3)
|
||
|
||
if the subobject is of scalar type,
|
||
the built-in assignment operator is used[.](#12.sentence-4)
|
||
|
||
It is unspecified whether subobjects representing virtual base classes
|
||
are assigned more than once by the implicitly-defined copy/move assignment
|
||
operator[.](#12.sentence-5)
|
||
|
||
[*Example [3](#example-3)*: struct V { };struct A : virtual V { };struct B : virtual V { };struct C : B, A { };
|
||
|
||
It is unspecified whether the virtual base class subobjectV is assigned twice by the implicitly-defined copy/move assignment operator forC[.](#12.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
[13](#13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2063)
|
||
|
||
The implicitly-defined copy/move assignment operator for a
|
||
union X copies the object representation ([[basic.types.general]](basic.types.general#term.object.representation "6.9.1 General")) of X[.](#13.sentence-1)
|
||
|
||
If the source and destination of the assignment are not the same object, then
|
||
for each object nested within ([[intro.object]](intro.object "6.8.2 Object model"))
|
||
the object that is the source of the copy,
|
||
a corresponding object o nested within the destination is created,
|
||
and the lifetime of o begins before the copy is performed[.](#13.sentence-2)
|
||
|
||
[14](#14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2072)
|
||
|
||
The implicitly-defined copy/move assignment operator for a class
|
||
returns the object for which the assignment operator is invoked,
|
||
that is, the object assigned to[.](#14.sentence-1)
|
||
|
||
[90)](#footnote-90)[90)](#footnoteref-90)
|
||
|
||
Because
|
||
a template assignment operator or an assignment operator
|
||
taking an rvalue reference parameter is never a copy assignment operator,
|
||
the presence of such an assignment operator does not suppress the
|
||
implicit declaration of a copy assignment operator[.](#footnote-90.sentence-1)
|
||
|
||
Such assignment operators
|
||
participate in overload resolution with other assignment operators, including
|
||
copy assignment operators, and, if selected, will be used to assign an object[.](#footnote-90.sentence-2)
|
||
|
||
[91)](#footnote-91)[91)](#footnoteref-91)
|
||
|
||
This implies that the reference parameter of the
|
||
implicitly-declared copy assignment operator cannot bind to avolatile lvalue; see [[diff.class]](diff.class "C.7.7 [class]: classes")[.](#footnote-91.sentence-1)
|