This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View 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.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)

301
cppdraft/class/copy/ctor.md Normal file
View 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.7Default 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.7Default 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.3Copy/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.6Function 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.6Implicit 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.3Deleted 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.2Overload 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.1General")) 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.2Overload resolution"), [[over.over]](over.over "12.3Address 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.3Virtual functions"))
and no virtual base classes ([[class.mi]](class.mi "11.7.2Multiple 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.3Copy/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.3One-definition rule"), [[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#12.sentence-1)
— *end note*]
If an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions")) constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The 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.5Exception 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.3Initializing 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.3Initializing 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.1General")) of X[.](#15.sentence-1)
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 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)

View 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.4The return statement")) in
a function with a class return type,
when the [*expression*](expr.comma#nt:expression "7.6.20Comma 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.1Preamble[except.pre]") of a[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling 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.18Throwing an exception[expr.throw]") ([[expr.throw]](expr.throw "7.6.18Throwing 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.1Preamble[except.pre]") of a [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]"))
that belongs to a scope that does not contain
the innermost enclosing [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") associated with a [*try-block*](except.pre#nt:try-block "14.1Preamble[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.4Coroutine 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.1Preamble[except.pre]") of a[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling 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.1Preamble[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.1Preamble[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.7Constant expressions"))
and in constant initialization ([[basic.start.static]](basic.start.static "6.10.3.2Static 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.7Constant 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*]