- tmp/tmpx4knr0vz/{from.md → to.md} +106 -88
tmp/tmpx4knr0vz/{from.md → to.md}
RENAMED
|
@@ -1,51 +1,62 @@
|
|
| 1 |
-
## Destructors <a id="class.dtor">[[class.dtor]]</a>
|
| 2 |
|
| 3 |
-
|
| 4 |
-
declarator
|
| 5 |
|
| 6 |
``` bnf
|
| 7 |
ptr-declarator '(' parameter-declaration-clause ')' noexcept-specifierₒₚₜ attribute-specifier-seqₒₚₜ
|
| 8 |
```
|
| 9 |
|
| 10 |
where the *ptr-declarator* consists solely of an *id-expression*, an
|
| 11 |
optional *attribute-specifier-seq*, and optional surrounding
|
| 12 |
parentheses, and the *id-expression* has one of the following forms:
|
| 13 |
|
| 14 |
- in a *member-declaration* that belongs to the *member-specification*
|
| 15 |
-
of a class but is not a friend declaration
|
| 16 |
-
*id-expression* is `~`*class-name* and the
|
| 17 |
-
injected-class-name
|
| 18 |
-
|
| 19 |
-
- in a *member-declaration* that belongs to the *member-specification*
|
| 20 |
-
of a class template but is not a friend declaration, the
|
| 21 |
-
*id-expression* is `~`*class-name* and the *class-name* names the
|
| 22 |
-
current instantiation ([[temp.dep.type]]) of the
|
| 23 |
-
immediately-enclosing class template; or
|
| 24 |
- in a declaration at namespace scope or in a friend declaration, the
|
| 25 |
*id-expression* is *nested-name-specifier* `~`*class-name* and the
|
| 26 |
*class-name* names the same class as the *nested-name-specifier*.
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
`
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
[*Note 1*: A declaration of a destructor that does not have a
|
| 41 |
-
*noexcept-specifier* has the same exception specification as if
|
| 42 |
-
implicitly declared
|
| 43 |
-
|
| 44 |
-
If a class has no user-declared destructor, a destructor is implicitly
|
| 45 |
-
declared as defaulted ([[dcl.fct.def]]). An implicitly-declared
|
| 46 |
-
destructor is an `inline` `public` member of its class.
|
| 47 |
|
| 48 |
A defaulted destructor for a class `X` is defined as deleted if:
|
| 49 |
|
| 50 |
- `X` is a union-like class that has a variant member with a non-trivial
|
| 51 |
destructor,
|
|
@@ -64,85 +75,90 @@ A destructor is trivial if it is not user-provided and if:
|
|
| 64 |
- for all of the non-static data members of its class that are of class
|
| 65 |
type (or array thereof), each such class has a trivial destructor.
|
| 66 |
|
| 67 |
Otherwise, the destructor is *non-trivial*.
|
| 68 |
|
|
|
|
|
|
|
|
|
|
| 69 |
A destructor that is defaulted and not defined as deleted is *implicitly
|
| 70 |
-
defined* when it is odr-used
|
| 71 |
-
|
| 72 |
|
| 73 |
-
Before
|
| 74 |
-
|
| 75 |
-
|
| 76 |
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
destructors for the members and bases are called. Destructors for
|
| 90 |
elements of an array are called in reverse order of their construction
|
| 91 |
(see [[class.init]]).
|
| 92 |
|
| 93 |
-
A destructor can be declared `virtual` ([[class.virtual]]) or pure
|
| 94 |
-
`virtual` ([[class.abstract]]); if any objects of that class or any
|
| 95 |
-
derived class are created in the program, the destructor shall be
|
| 96 |
-
defined. If a class has a base class with a virtual destructor, its
|
| 97 |
-
destructor (whether user- or implicitly-declared) is virtual.
|
| 98 |
-
|
| 99 |
-
[*Note 2*: Some language constructs have special semantics when used
|
| 100 |
-
during destruction; see [[class.cdtor]]. — *end note*]
|
| 101 |
-
|
| 102 |
A destructor is invoked implicitly
|
| 103 |
|
| 104 |
-
- for a constructed object with static storage duration
|
| 105 |
-
[[basic.stc.static]]
|
| 106 |
-
- for a constructed object with thread storage duration
|
| 107 |
-
[[basic.stc.thread]]
|
| 108 |
-
- for a constructed object with automatic storage duration
|
| 109 |
-
[[basic.stc.auto]]
|
| 110 |
-
|
| 111 |
- for a constructed temporary object when its lifetime ends (
|
| 112 |
[[conv.rval]], [[class.temporary]]).
|
| 113 |
|
| 114 |
In each case, the context of the invocation is the context of the
|
| 115 |
-
construction of the object. A destructor
|
| 116 |
-
through use of a *delete-expression*
|
| 117 |
-
|
| 118 |
-
|
| 119 |
|
| 120 |
[*Note 3*: An array of class type contains several subobjects for each
|
| 121 |
of which the destructor is invoked. — *end note*]
|
| 122 |
|
| 123 |
A destructor can also be invoked explicitly. A destructor is
|
| 124 |
*potentially invoked* if it is invoked or as specified in [[expr.new]],
|
| 125 |
-
[[
|
| 126 |
-
|
| 127 |
-
the context of the
|
|
|
|
| 128 |
|
| 129 |
At the point of definition of a virtual destructor (including an
|
| 130 |
-
implicit definition
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
|
| 136 |
[*Note 4*: This assures that a deallocation function corresponding to
|
| 137 |
-
the dynamic type of an object is available for the *delete-expression*
|
| 138 |
-
[[class.free]]
|
| 139 |
|
| 140 |
In an explicit destructor call, the destructor is specified by a `~`
|
| 141 |
followed by a *type-name* or *decltype-specifier* that denotes the
|
| 142 |
destructor’s class type. The invocation of a destructor is subject to
|
| 143 |
-
the usual rules for member functions
|
| 144 |
object is not of the destructor’s class type and not of a class derived
|
| 145 |
from the destructor’s class type (including when the destructor is
|
| 146 |
invoked via a null pointer value), the program has undefined behavior.
|
| 147 |
|
| 148 |
[*Note 5*: Invoking `delete` on a null pointer does not call the
|
|
@@ -172,14 +188,14 @@ void f() {
|
|
| 172 |
```
|
| 173 |
|
| 174 |
— *end example*]
|
| 175 |
|
| 176 |
[*Note 6*: An explicit destructor call must always be written using a
|
| 177 |
-
member access operator
|
| 178 |
-
[[expr.prim]]
|
| 179 |
-
function is not an explicit destructor call
|
| 180 |
-
[[expr.unary.op]]
|
| 181 |
|
| 182 |
[*Note 7*:
|
| 183 |
|
| 184 |
Explicit calls of destructors are rarely needed. One use of such calls
|
| 185 |
is for objects placed at specific addresses using a placement
|
|
@@ -205,27 +221,29 @@ void g() { // rare, specialized use:
|
|
| 205 |
|
| 206 |
— *end note*]
|
| 207 |
|
| 208 |
Once a destructor is invoked for an object, the object no longer exists;
|
| 209 |
the behavior is undefined if the destructor is invoked for an object
|
| 210 |
-
whose lifetime has ended
|
| 211 |
|
| 212 |
-
[*Example 2*: If the destructor for an
|
| 213 |
-
invoked, and the block is subsequently left in a
|
| 214 |
-
ordinarily invoke implicit destruction of the object,
|
| 215 |
-
undefined. — *end example*]
|
| 216 |
|
| 217 |
[*Note 8*:
|
| 218 |
|
| 219 |
The notation for explicit call of a destructor can be used for any
|
| 220 |
-
scalar type name
|
| 221 |
-
write code without having to know if a destructor exists for a given
|
| 222 |
type. For example:
|
| 223 |
|
| 224 |
``` cpp
|
| 225 |
typedef int I;
|
| 226 |
I* p;
|
| 227 |
p->I::~I();
|
| 228 |
```
|
| 229 |
|
| 230 |
— *end note*]
|
| 231 |
|
|
|
|
|
|
|
|
|
| 1 |
+
### Destructors <a id="class.dtor">[[class.dtor]]</a>
|
| 2 |
|
| 3 |
+
A *prospective destructor* is introduced by a declaration whose
|
| 4 |
+
*declarator* is a function declarator [[dcl.fct]] of the form
|
| 5 |
|
| 6 |
``` bnf
|
| 7 |
ptr-declarator '(' parameter-declaration-clause ')' noexcept-specifierₒₚₜ attribute-specifier-seqₒₚₜ
|
| 8 |
```
|
| 9 |
|
| 10 |
where the *ptr-declarator* consists solely of an *id-expression*, an
|
| 11 |
optional *attribute-specifier-seq*, and optional surrounding
|
| 12 |
parentheses, and the *id-expression* has one of the following forms:
|
| 13 |
|
| 14 |
- in a *member-declaration* that belongs to the *member-specification*
|
| 15 |
+
of a class or class template but is not a friend declaration
|
| 16 |
+
[[class.friend]], the *id-expression* is `~`*class-name* and the
|
| 17 |
+
*class-name* is the injected-class-name [[class.pre]] of the
|
| 18 |
+
immediately-enclosing entity or
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
- in a declaration at namespace scope or in a friend declaration, the
|
| 20 |
*id-expression* is *nested-name-specifier* `~`*class-name* and the
|
| 21 |
*class-name* names the same class as the *nested-name-specifier*.
|
| 22 |
|
| 23 |
+
A prospective destructor shall take no arguments [[dcl.fct]]. Each
|
| 24 |
+
*decl-specifier* of the *decl-specifier-seq* of a prospective destructor
|
| 25 |
+
declaration (if any) shall be `friend`, `inline`, `virtual`,
|
| 26 |
+
`constexpr`, or `consteval`.
|
| 27 |
+
|
| 28 |
+
If a class has no user-declared prospective destructor, a prospective
|
| 29 |
+
destructor is implicitly declared as defaulted [[dcl.fct.def]]. An
|
| 30 |
+
implicitly-declared prospective destructor is an inline public member of
|
| 31 |
+
its class.
|
| 32 |
+
|
| 33 |
+
An implicitly-declared prospective destructor for a class `X` will have
|
| 34 |
+
the form
|
| 35 |
+
|
| 36 |
+
``` cpp
|
| 37 |
+
~X()
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
At the end of the definition of a class, overload resolution is
|
| 41 |
+
performed among the prospective destructors declared in that class with
|
| 42 |
+
an empty argument list to select the *destructor* for the class, also
|
| 43 |
+
known as the *selected destructor*. The program is ill-formed if
|
| 44 |
+
overload resolution fails. Destructor selection does not constitute a
|
| 45 |
+
reference to, or odr-use [[basic.def.odr]] of, the selected destructor,
|
| 46 |
+
and in particular, the selected destructor may be deleted
|
| 47 |
+
[[dcl.fct.def.delete]].
|
| 48 |
+
|
| 49 |
+
The address of a destructor shall not be taken. A destructor can be
|
| 50 |
+
invoked for a `const`, `volatile` or `const` `volatile` object. `const`
|
| 51 |
+
and `volatile` semantics [[dcl.type.cv]] are not applied on an object
|
| 52 |
+
under destruction. They stop being in effect when the destructor for the
|
| 53 |
+
most derived object [[intro.object]] starts.
|
| 54 |
|
| 55 |
[*Note 1*: A declaration of a destructor that does not have a
|
| 56 |
+
*noexcept-specifier* has the same exception specification as if it had
|
| 57 |
+
been implicitly declared [[except.spec]]. — *end note*]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
A defaulted destructor for a class `X` is defined as deleted if:
|
| 60 |
|
| 61 |
- `X` is a union-like class that has a variant member with a non-trivial
|
| 62 |
destructor,
|
|
|
|
| 75 |
- for all of the non-static data members of its class that are of class
|
| 76 |
type (or array thereof), each such class has a trivial destructor.
|
| 77 |
|
| 78 |
Otherwise, the destructor is *non-trivial*.
|
| 79 |
|
| 80 |
+
A defaulted destructor is a constexpr destructor if it satisfies the
|
| 81 |
+
requirements for a constexpr destructor [[dcl.constexpr]].
|
| 82 |
+
|
| 83 |
A destructor that is defaulted and not defined as deleted is *implicitly
|
| 84 |
+
defined* when it is odr-used [[basic.def.odr]] or when it is explicitly
|
| 85 |
+
defaulted after its first declaration.
|
| 86 |
|
| 87 |
+
Before a defaulted destructor for a class is implicitly defined, all the
|
| 88 |
+
non-user-provided destructors for its base classes and its non-static
|
| 89 |
+
data members are implicitly defined.
|
| 90 |
|
| 91 |
+
A prospective destructor can be declared `virtual` [[class.virtual]] or
|
| 92 |
+
pure `virtual` [[class.abstract]]. If the destructor of a class is
|
| 93 |
+
virtual and any objects of that class or any derived class are created
|
| 94 |
+
in the program, the destructor shall be defined. If a class has a base
|
| 95 |
+
class with a virtual destructor, its destructor (whether user- or
|
| 96 |
+
implicitly-declared) is virtual.
|
| 97 |
+
|
| 98 |
+
[*Note 2*: Some language constructs have special semantics when used
|
| 99 |
+
during destruction; see [[class.cdtor]]. — *end note*]
|
| 100 |
+
|
| 101 |
+
After executing the body of the destructor and destroying any objects
|
| 102 |
+
with automatic storage duration allocated within the body, a destructor
|
| 103 |
+
for class `X` calls the destructors for `X`’s direct non-variant
|
| 104 |
+
non-static data members, the destructors for `X`’s non-virtual direct
|
| 105 |
+
base classes and, if `X` is the most derived class [[class.base.init]],
|
| 106 |
+
its destructor calls the destructors for `X`’s virtual base classes. All
|
| 107 |
+
destructors are called as if they were referenced with a qualified name,
|
| 108 |
+
that is, ignoring any possible virtual overriding destructors in more
|
| 109 |
+
derived classes. Bases and members are destroyed in the reverse order of
|
| 110 |
+
the completion of their constructor (see [[class.base.init]]). A
|
| 111 |
+
`return` statement [[stmt.return]] in a destructor might not directly
|
| 112 |
+
return to the caller; before transferring control to the caller, the
|
| 113 |
destructors for the members and bases are called. Destructors for
|
| 114 |
elements of an array are called in reverse order of their construction
|
| 115 |
(see [[class.init]]).
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
A destructor is invoked implicitly
|
| 118 |
|
| 119 |
+
- for a constructed object with static storage duration
|
| 120 |
+
[[basic.stc.static]] at program termination [[basic.start.term]],
|
| 121 |
+
- for a constructed object with thread storage duration
|
| 122 |
+
[[basic.stc.thread]] at thread exit,
|
| 123 |
+
- for a constructed object with automatic storage duration
|
| 124 |
+
[[basic.stc.auto]] when the block in which an object is created exits
|
| 125 |
+
[[stmt.dcl]],
|
| 126 |
- for a constructed temporary object when its lifetime ends (
|
| 127 |
[[conv.rval]], [[class.temporary]]).
|
| 128 |
|
| 129 |
In each case, the context of the invocation is the context of the
|
| 130 |
+
construction of the object. A destructor may also be invoked implicitly
|
| 131 |
+
through use of a *delete-expression* [[expr.delete]] for a constructed
|
| 132 |
+
object allocated by a *new-expression* [[expr.new]]; the context of the
|
| 133 |
+
invocation is the *delete-expression*.
|
| 134 |
|
| 135 |
[*Note 3*: An array of class type contains several subobjects for each
|
| 136 |
of which the destructor is invoked. — *end note*]
|
| 137 |
|
| 138 |
A destructor can also be invoked explicitly. A destructor is
|
| 139 |
*potentially invoked* if it is invoked or as specified in [[expr.new]],
|
| 140 |
+
[[stmt.return]], [[dcl.init.aggr]], [[class.base.init]], and
|
| 141 |
+
[[except.throw]]. A program is ill-formed if a destructor that is
|
| 142 |
+
potentially invoked is deleted or not accessible from the context of the
|
| 143 |
+
invocation.
|
| 144 |
|
| 145 |
At the point of definition of a virtual destructor (including an
|
| 146 |
+
implicit definition [[class.dtor]]), the non-array deallocation function
|
| 147 |
+
is determined as if for the expression `delete this` appearing in a
|
| 148 |
+
non-virtual destructor of the destructor’s class (see [[expr.delete]]).
|
| 149 |
+
If the lookup fails or if the deallocation function has a deleted
|
| 150 |
+
definition [[dcl.fct.def]], the program is ill-formed.
|
| 151 |
|
| 152 |
[*Note 4*: This assures that a deallocation function corresponding to
|
| 153 |
+
the dynamic type of an object is available for the *delete-expression*
|
| 154 |
+
[[class.free]]. — *end note*]
|
| 155 |
|
| 156 |
In an explicit destructor call, the destructor is specified by a `~`
|
| 157 |
followed by a *type-name* or *decltype-specifier* that denotes the
|
| 158 |
destructor’s class type. The invocation of a destructor is subject to
|
| 159 |
+
the usual rules for member functions [[class.mfct]]; that is, if the
|
| 160 |
object is not of the destructor’s class type and not of a class derived
|
| 161 |
from the destructor’s class type (including when the destructor is
|
| 162 |
invoked via a null pointer value), the program has undefined behavior.
|
| 163 |
|
| 164 |
[*Note 5*: Invoking `delete` on a null pointer does not call the
|
|
|
|
| 188 |
```
|
| 189 |
|
| 190 |
— *end example*]
|
| 191 |
|
| 192 |
[*Note 6*: An explicit destructor call must always be written using a
|
| 193 |
+
member access operator [[expr.ref]] or a *qualified-id*
|
| 194 |
+
[[expr.prim.id.qual]]; in particular, the *unary-expression* `~X()` in a
|
| 195 |
+
member function is not an explicit destructor call
|
| 196 |
+
[[expr.unary.op]]. — *end note*]
|
| 197 |
|
| 198 |
[*Note 7*:
|
| 199 |
|
| 200 |
Explicit calls of destructors are rarely needed. One use of such calls
|
| 201 |
is for objects placed at specific addresses using a placement
|
|
|
|
| 221 |
|
| 222 |
— *end note*]
|
| 223 |
|
| 224 |
Once a destructor is invoked for an object, the object no longer exists;
|
| 225 |
the behavior is undefined if the destructor is invoked for an object
|
| 226 |
+
whose lifetime has ended [[basic.life]].
|
| 227 |
|
| 228 |
+
[*Example 2*: If the destructor for an object with automatic storage
|
| 229 |
+
duration is explicitly invoked, and the block is subsequently left in a
|
| 230 |
+
manner that would ordinarily invoke implicit destruction of the object,
|
| 231 |
+
the behavior is undefined. — *end example*]
|
| 232 |
|
| 233 |
[*Note 8*:
|
| 234 |
|
| 235 |
The notation for explicit call of a destructor can be used for any
|
| 236 |
+
scalar type name [[expr.prim.id.dtor]]. Allowing this makes it possible
|
| 237 |
+
to write code without having to know if a destructor exists for a given
|
| 238 |
type. For example:
|
| 239 |
|
| 240 |
``` cpp
|
| 241 |
typedef int I;
|
| 242 |
I* p;
|
| 243 |
p->I::~I();
|
| 244 |
```
|
| 245 |
|
| 246 |
— *end note*]
|
| 247 |
|
| 248 |
+
A destructor shall not be a coroutine.
|
| 249 |
+
|