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