Files
2025-10-25 03:02:53 +03:00

310 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.6Copy/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.6Function 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.6Implicit 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.2Overload 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.1General")) 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.2Overload resolution"), [[over.over]](over.over "12.3Address 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.2Simple assignment"))[.](#8.sentence-1)
[*Note [5](#note-5)*:
A [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The 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.3Virtual functions"))
and no virtual base classes ([[class.mi]](class.mi "11.7.2Multiple 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.6Copy/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.2Explicitly-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.5Exception 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.1General[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.1General")) 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.2Object 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)