Init
This commit is contained in:
309
cppdraft/class/copy/assign.md
Normal file
309
cppdraft/class/copy/assign.md
Normal file
@@ -0,0 +1,309 @@
|
||||
[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)
|
||||
301
cppdraft/class/copy/ctor.md
Normal file
301
cppdraft/class/copy/ctor.md
Normal file
@@ -0,0 +1,301 @@
|
||||
[class.copy.ctor]
|
||||
|
||||
# 11 Classes [[class]](./#class)
|
||||
|
||||
## 11.4 Class members [[class.mem]](class.mem#class.copy.ctor)
|
||||
|
||||
### 11.4.5 Constructors [[class.ctor]](class.ctor#class.copy.ctor)
|
||||
|
||||
#### 11.4.5.3 Copy/move constructors [class.copy.ctor]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1477)
|
||||
|
||||
A non-template constructor for classX is
|
||||
a
|
||||
copy
|
||||
constructor if its first parameter is of typeX&,const X&,volatile X& orconst volatile X&,
|
||||
and either there are no other parameters
|
||||
or else all other parameters have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#1.sentence-1)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
X::X(const X&) andX::X(X&,int=1) are copy constructors[.](#1.sentence-2)
|
||||
|
||||
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*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1512)
|
||||
|
||||
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]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#2.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
Y::Y(Y&&) is a move constructor[.](#2.sentence-2)
|
||||
|
||||
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*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1531)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
All forms of copy/move constructor can be declared for a class[.](#3.sentence-1)
|
||||
|
||||
[*Example [3](#example-3)*: struct X { X(const X&);
|
||||
X(X&); // OK X(X&&);
|
||||
X(const X&&); // OK, but possibly not sensible}; â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1546)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
If a classX only has a copy constructor with a parameter of typeX&,
|
||||
an initializer of typeconstX orvolatileX cannot initialize an object of typecv X[.](#4.sentence-1)
|
||||
|
||||
[*Example [4](#example-4)*: 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*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1572)
|
||||
|
||||
A declaration of a constructor for a classX is ill-formed if its first parameter is of typecv X and either there are no other parameters or else all other parameters have
|
||||
default arguments[.](#5.sentence-1)
|
||||
|
||||
A member function template is never instantiated to
|
||||
produce such a constructor signature[.](#5.sentence-2)
|
||||
|
||||
[*Example [5](#example-5)*: 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*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1597)
|
||||
|
||||
If the class definition does not explicitly declare a copy constructor,
|
||||
a non-explicit one is declared [*implicitly*](#def:constructor,copy,implicitly_declared "11.4.5.3 Copy/move constructors [class.copy.ctor]")[.](#6.sentence-1)
|
||||
|
||||
If the class definition declares a move
|
||||
constructor or move assignment operator, the implicitly declared copy
|
||||
constructor is defined as deleted; otherwise, it is
|
||||
defaulted ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions"))[.](#6.sentence-2)
|
||||
|
||||
The latter case is deprecated if the class has a user-declared copy assignment
|
||||
operator or a user-declared destructor ([[depr.impldec]](depr.impldec "D.6 Implicit declaration of copy functions"))[.](#6.sentence-3)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1607)
|
||||
|
||||
The implicitly-declared copy constructor for a classX will have the formX::X(const X&) if each potentially constructed subobject of a class typeM (or array thereof)
|
||||
has a copy constructor whose first parameter is of typeconstM& orconstvolatileM&[.](#7.sentence-1)[89](#footnote-89 "This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue; see [diff.class].")
|
||||
|
||||
Otherwise, the implicitly-declared copy constructor will have the formX::X(X&)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1636)
|
||||
|
||||
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
|
||||
|
||||
- [(8.1)](#8.1)
|
||||
|
||||
X does not have a user-declared copy constructor,
|
||||
|
||||
- [(8.2)](#8.2)
|
||||
|
||||
X does not have a user-declared copy assignment operator,
|
||||
|
||||
- [(8.3)](#8.3)
|
||||
|
||||
X does not have a user-declared move assignment operator, and
|
||||
|
||||
- [(8.4)](#8.4)
|
||||
|
||||
X does not have a user-declared destructor[.](#8.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
When the move constructor is not implicitly declared or explicitly supplied,
|
||||
expressions that otherwise would have invoked the move constructor might instead invoke
|
||||
a copy constructor[.](#8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1661)
|
||||
|
||||
The implicitly-declared move constructor for class X will have the formX::X(X&&)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1667)
|
||||
|
||||
An implicitly-declared copy/move constructor is an
|
||||
inline public member of its class[.](#10.sentence-1)
|
||||
|
||||
A defaulted copy/move constructor for a class X is defined as deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3 Deleted definitions")) if X has:
|
||||
|
||||
- [(10.1)](#10.1)
|
||||
|
||||
a potentially constructed subobject of type M (or possibly multidimensional array thereof) for which
|
||||
overload resolution ([[over.match]](over.match "12.2 Overload resolution")), as applied to find M's corresponding constructor,
|
||||
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,
|
||||
|
||||
- [(10.2)](#10.2)
|
||||
|
||||
any potentially constructed subobject of
|
||||
class type M (or possibly multidimensional array thereof)
|
||||
where M has
|
||||
a destructor that is deleted or inaccessible from the defaulted
|
||||
constructor, or,
|
||||
|
||||
- [(10.3)](#10.3)
|
||||
|
||||
for the copy constructor, a non-static data member of rvalue reference type[.](#10.sentence-2)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
A defaulted move constructor 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"))[.](#10.sentence-3)
|
||||
|
||||
Such a constructor would otherwise interfere with initialization from
|
||||
an rvalue which can use the copy constructor instead[.](#10.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1696)
|
||||
|
||||
A copy/move constructor for classX is
|
||||
trivial
|
||||
if it is not user-provided and if
|
||||
|
||||
- [(11.1)](#11.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
|
||||
|
||||
- [(11.2)](#11.2)
|
||||
|
||||
the constructor selected to copy/move each direct base class subobject is trivial, and
|
||||
|
||||
- [(11.3)](#11.3)
|
||||
|
||||
for each non-static data member ofX 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*](#def:constructor,copy,nontrivial "11.4.5.3 Copy/move constructors [class.copy.ctor]")[.](#11.sentence-1)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1724)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
The copy/move constructor is implicitly defined even if the implementation elided
|
||||
its odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule"), [[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#12.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions")) constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers")),
|
||||
the implicitly-defined
|
||||
constructor is constexpr[.](#12.sentence-2)
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1733)
|
||||
|
||||
Before the defaulted copy/move constructor for a class is
|
||||
implicitly defined,
|
||||
all non-user-provided copy/move constructors for its
|
||||
potentially constructed subobjects
|
||||
are implicitly defined[.](#13.sentence-1)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
An implicitly-declared copy/move constructor has an
|
||||
implied exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))[.](#13.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1744)
|
||||
|
||||
The implicitly-defined copy/move constructor for a non-union classX performs a memberwise copy/move of its bases and members[.](#14.sentence-1)
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
Default member initializers of non-static data members are ignored[.](#14.sentence-2)
|
||||
|
||||
â *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]](class.base.init "11.9.3 Initializing bases and members"))[.](#14.sentence-3)
|
||||
|
||||
Let x be either the parameter of the constructor or, for the move constructor, an
|
||||
xvalue referring to the parameter[.](#14.sentence-4)
|
||||
|
||||
Each base or non-static data member
|
||||
is copied/moved in the manner appropriate to its type:
|
||||
|
||||
- [(14.1)](#14.1)
|
||||
|
||||
if the member is an array, each element is
|
||||
direct-initialized with the corresponding subobject of x;
|
||||
|
||||
- [(14.2)](#14.2)
|
||||
|
||||
if a member m has rvalue reference type T&&, it is direct-initialized withstatic_cast<T&&>(x.m);
|
||||
|
||||
- [(14.3)](#14.3)
|
||||
|
||||
otherwise, the base or member is direct-initialized with the corresponding base or member of x[.](#14.sentence-5)
|
||||
|
||||
Virtual base class subobjects shall be initialized only once by
|
||||
the implicitly-defined copy/move constructor (see [[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#14.sentence-6)
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1774)
|
||||
|
||||
The implicitly-defined copy/move constructor for a unionX copies the object representation ([[basic.types.general]](basic.types.general#term.object.representation "6.9.1 General")) of X[.](#15.sentence-1)
|
||||
|
||||
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 identified (if the object is a subobject) or created (otherwise),
|
||||
and the lifetime of o begins before the copy is performed[.](#15.sentence-2)
|
||||
|
||||
[89)](#footnote-89)[89)](#footnoteref-89)
|
||||
|
||||
This implies that the reference parameter of the
|
||||
implicitly-declared copy constructor
|
||||
cannot bind to avolatile lvalue; see [[diff.class]](diff.class "C.7.7 [class]: classes")[.](#footnote-89.sentence-1)
|
||||
145
cppdraft/class/copy/elision.md
Normal file
145
cppdraft/class/copy/elision.md
Normal file
@@ -0,0 +1,145 @@
|
||||
[class.copy.elision]
|
||||
|
||||
# 11 Classes [[class]](./#class)
|
||||
|
||||
## 11.9 Initialization [[class.init]](class.init#class.copy.elision)
|
||||
|
||||
### 11.9.6 Copy/move elision [class.copy.elision]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6354)
|
||||
|
||||
When certain criteria are met, an implementation is
|
||||
allowed to omit the creation of a class object from
|
||||
a source object of the same type (ignoring cv-qualification),
|
||||
even if the selected constructor and/or the
|
||||
destructor for the object haveside effects[.](#1.sentence-1)
|
||||
|
||||
In such cases, the
|
||||
implementation treats the source and target of the
|
||||
omitted initialization as simply two different ways of
|
||||
referring to the same object[.](#1.sentence-2)
|
||||
|
||||
If the first parameter of the
|
||||
selected constructor is an rvalue reference to the object's type,
|
||||
the destruction of that object occurs when the target would have been destroyed;
|
||||
otherwise, the destruction occurs at the later of the times when the
|
||||
two objects would have been destroyed without the
|
||||
optimization[.](#1.sentence-3)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Because only one object is destroyed instead of two,
|
||||
and the creation of one object is omitted,
|
||||
there is still one object destroyed for each one constructed[.](#1.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
This elision of object creation, called[*copy elision*](#def:copy_elision),
|
||||
is permitted in the
|
||||
following circumstances (which may be combined to
|
||||
eliminate multiple copies):
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
in a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")) in
|
||||
a function with a class return type,
|
||||
when the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is the name of a non-volatile
|
||||
object o with automatic storage duration (other than a function parameter or a variable
|
||||
introduced by the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") of a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling an exception"))),
|
||||
the copy-initialization of the result object can be
|
||||
omitted by constructing o directly
|
||||
into the function call's result object;
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
in a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]") ([[expr.throw]](expr.throw "7.6.18 Throwing an exception")), when the operand
|
||||
is the name of a non-volatile object o with automatic storage duration
|
||||
(other than a function parameter or
|
||||
a variable introduced by
|
||||
the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]"))
|
||||
that belongs to a scope that does not contain
|
||||
the innermost enclosing [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") associated with a [*try-block*](except.pre#nt:try-block "14.1 Preamble [except.pre]") (if there is one),
|
||||
the copy-initialization of the exception object can be omitted by
|
||||
constructing o directly into the exception object;
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
in a [coroutine](dcl.fct.def.coroutine "9.6.4 Coroutine definitions [dcl.fct.def.coroutine]"), a copy of a coroutine parameter
|
||||
can be omitted and references to that copy replaced with references to the
|
||||
corresponding parameter if the meaning of the program will be unchanged except for
|
||||
the execution of a constructor and destructor for the parameter copy object;
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
when the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") of a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling an exception")) declares an object o,
|
||||
the copy-initialization of o can be omitted by treating
|
||||
the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") as an alias for the exception
|
||||
object if the meaning of the program will be unchanged except for the execution
|
||||
of constructors and destructors for the object declared by the[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]")[.](#1.sentence-5)
|
||||
[*Note [2](#note-2)*:
|
||||
There cannot be a move from the exception object because it is
|
||||
always an lvalue[.](#1.4.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
Copy elision is not permitted
|
||||
where an expression is evaluated in a context
|
||||
requiring a constant expression ([[expr.const]](expr.const "7.7 Constant expressions"))
|
||||
and in constant initialization ([[basic.start.static]](basic.start.static "6.10.3.2 Static initialization"))[.](#1.sentence-6)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
It is possible that copy elision is performed
|
||||
if the same expression
|
||||
is evaluated in another context[.](#1.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6436)
|
||||
|
||||
[*Example [1](#example-1)*: class Thing {public: Thing(); ~Thing();
|
||||
Thing(const Thing&);};
|
||||
|
||||
Thing f() { Thing t; return t;} Thing t2 = f();
|
||||
|
||||
struct A {void *p; constexpr A(): p(this) {}};
|
||||
|
||||
constexpr A g() { A loc; return loc;}constexpr A a; // well-formed, a.p points to aconstexpr A b = g(); // error: b.p would be dangling ([[expr.const]](expr.const "7.7 Constant expressions"))void h() { A c = g(); // well-formed, c.p can point to c or be dangling}
|
||||
|
||||
Here the criteria for elision can eliminate
|
||||
the copying of the object t with automatic storage duration
|
||||
into the result object for the function call f(),
|
||||
which is the non-local object t2[.](#2.sentence-1)
|
||||
|
||||
Effectively, the construction of t can be viewed as directly initializing t2,
|
||||
and that object's destruction will occur at program exit[.](#2.sentence-2)
|
||||
|
||||
Adding a move constructor to Thing has the same effect, but it is the
|
||||
move construction from the object with automatic storage duration to t2 that is elided[.](#2.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6481)
|
||||
|
||||
[*Example [2](#example-2)*: class Thing {public: Thing(); ~Thing();
|
||||
Thing(Thing&&);private: Thing(const Thing&);};
|
||||
|
||||
Thing f(bool b) { Thing t; if (b)throw t; // OK, Thing(Thing&&) used (or elided) to throw treturn t; // OK, Thing(Thing&&) used (or elided) to return t} Thing t2 = f(false); // OK, no extra copy/move performed, t2 constructed by call to fstruct Weird { Weird();
|
||||
Weird(Weird&);};
|
||||
|
||||
Weird g(bool b) {static Weird w1;
|
||||
Weird w2; if (b)return w1; // OK, uses Weird(Weird&)elsereturn w2; // error: w2 in this context is an xvalue}int& h(bool b, int i) {static int s; if (b)return s; // OKelsereturn i; // error: i is an xvalue}decltype(auto) h2(Thing t) {return t; // OK, t is an xvalue and h2's return type is Thing}decltype(auto) h3(Thing t) {return (t); // OK, (t) is an xvalue and h3's return type is Thing&&} â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6534)
|
||||
|
||||
[*Example [3](#example-3)*: template<class T> void g(const T&);
|
||||
|
||||
template<class T> void f() { T x; try { T y; try { g(x); }catch (...) {if (/*...*/)throw x; // does not movethrow y; // moves} g(y); } catch(...) { g(x);
|
||||
g(y); // error: y is not in scope}} â *end example*]
|
||||
Reference in New Issue
Block a user