tmp/tmp3m9lxnx0/{from.md → to.md}
RENAMED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
## Destructors <a id="class.dtor">[[class.dtor]]</a>
|
| 2 |
|
| 3 |
-
|
| 4 |
-
of the form
|
| 5 |
|
| 6 |
``` bnf
|
| 7 |
-
ptr-declarator '(' parameter-declaration-clause ')'
|
| 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:
|
|
@@ -24,24 +24,24 @@ parentheses, and the *id-expression* has one of the following forms:
|
|
| 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 |
The *class-name* shall not be a *typedef-name*. A destructor shall take
|
| 29 |
-
no arguments ([[dcl.fct]]).
|
| 30 |
-
*decl-specifier* of
|
| 31 |
-
`inline`, or `virtual`.
|
| 32 |
|
| 33 |
A destructor is used to destroy objects of its class type. The address
|
| 34 |
of a destructor shall not be taken. A destructor can be invoked for a
|
| 35 |
`const`, `volatile` or `const` `volatile` object. `const` and `volatile`
|
| 36 |
semantics ([[dcl.type.cv]]) are not applied on an object under
|
| 37 |
destruction. They stop being in effect when the destructor for the most
|
| 38 |
derived object ([[intro.object]]) starts.
|
| 39 |
|
| 40 |
-
A declaration of a destructor that does not have
|
| 41 |
-
*
|
| 42 |
-
|
| 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 |
|
|
@@ -65,41 +65,41 @@ A destructor is trivial if it is not user-provided and if:
|
|
| 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 ([[basic.def.odr]])
|
| 71 |
-
|
| 72 |
-
after its first declaration.
|
| 73 |
|
| 74 |
Before the defaulted destructor for a class is implicitly defined, all
|
| 75 |
the non-user-provided destructors for its base classes and its
|
| 76 |
non-static data members shall have been implicitly defined.
|
| 77 |
|
| 78 |
After executing the body of the destructor and destroying any automatic
|
| 79 |
objects allocated within the body, a destructor for class `X` calls the
|
| 80 |
destructors for `X`’s direct non-variant non-static data members, the
|
| 81 |
-
destructors for `X`’s direct base classes and, if `X` is the
|
| 82 |
-
most derived class ([[class.base.init]]), its destructor
|
| 83 |
-
destructors for `X`’s virtual base classes. All destructors
|
| 84 |
-
as if they were referenced with a qualified name, that is,
|
| 85 |
-
possible virtual overriding destructors in more derived
|
| 86 |
-
and members are destroyed in the reverse order of the
|
| 87 |
-
their constructor (see [[class.base.init]]). A `return`
|
| 88 |
-
[[stmt.return]]) in a destructor might not directly return
|
| 89 |
-
caller; before transferring control to the caller, the
|
| 90 |
-
the members and bases are called. Destructors for
|
| 91 |
-
are called in reverse order of their construction
|
|
|
|
| 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 |
-
|
| 100 |
-
destruction; see [[class.cdtor]].
|
| 101 |
|
| 102 |
A destructor is invoked implicitly
|
| 103 |
|
| 104 |
- for a constructed object with static storage duration (
|
| 105 |
[[basic.stc.static]]) at program termination ([[basic.start.term]]),
|
|
@@ -107,44 +107,50 @@ A destructor is invoked implicitly
|
|
| 107 |
[[basic.stc.thread]]) at thread exit,
|
| 108 |
- for a constructed object with automatic storage duration (
|
| 109 |
[[basic.stc.auto]]) when the block in which an object is created
|
| 110 |
exits ([[stmt.dcl]]),
|
| 111 |
- for a constructed temporary object when its lifetime ends (
|
| 112 |
-
[[class.temporary]]).
|
| 113 |
|
| 114 |
In each case, the context of the invocation is the context of the
|
| 115 |
construction of the object. A destructor is also invoked implicitly
|
| 116 |
through use of a *delete-expression* ([[expr.delete]]) for a
|
| 117 |
constructed object allocated by a *new-expression* ([[expr.new]]); the
|
| 118 |
-
context of the invocation is the *delete-expression*.
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
At the point of definition of a virtual destructor (including an
|
| 127 |
implicit definition ([[class.copy]])), the non-array deallocation
|
| 128 |
-
function is
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
deallocation function or a function with a deleted definition (
|
| 133 |
-
[[dcl.fct.def]]), the program is ill-formed. This assures that a
|
| 134 |
-
deallocation function corresponding to the dynamic type of an object is
|
| 135 |
-
available for the *delete-expression* ([[class.free]]).
|
| 136 |
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
followed by a *type-name* or *decltype-specifier* that denotes the
|
| 139 |
destructor’s class type. The invocation of a destructor is subject to
|
| 140 |
the usual rules for member functions ([[class.mfct]]); that is, if the
|
| 141 |
object is not of the destructor’s class type and not of a class derived
|
| 142 |
from the destructor’s class type (including when the destructor is
|
| 143 |
invoked via a null pointer value), the program has undefined behavior.
|
| 144 |
-
|
| 145 |
-
[
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
``` cpp
|
| 148 |
struct B {
|
| 149 |
virtual ~B() { }
|
| 150 |
};
|
|
@@ -163,20 +169,25 @@ void f() {
|
|
| 163 |
B_ptr->B_alias::~B(); // calls B's destructor
|
| 164 |
B_ptr->B_alias::~B_alias(); // calls B's destructor
|
| 165 |
}
|
| 166 |
```
|
| 167 |
|
| 168 |
-
|
| 169 |
-
operator ([[expr.ref]]) or a qualified-id ([[expr.prim]]); in
|
| 170 |
-
particular, the *unary-expression* `~X()` in a member function is not an
|
| 171 |
-
explicit destructor call ([[expr.unary.op]]).
|
| 172 |
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
``` cpp
|
| 180 |
void* operator new(std::size_t, void* p) { return p; }
|
| 181 |
struct X {
|
| 182 |
X(int);
|
|
@@ -190,23 +201,31 @@ void g() { // rare, specialized use:
|
|
| 190 |
f(p);
|
| 191 |
p->X::~X(); // cleanup
|
| 192 |
}
|
| 193 |
```
|
| 194 |
|
|
|
|
|
|
|
| 195 |
Once a destructor is invoked for an object, the object no longer exists;
|
| 196 |
the behavior is undefined if the destructor is invoked for an object
|
| 197 |
-
whose lifetime has ended ([[basic.life]]).
|
| 198 |
-
automatic object is explicitly invoked, and the block is subsequently
|
| 199 |
-
left in a manner that would ordinarily invoke implicit destruction of
|
| 200 |
-
the object, the behavior is undefined.
|
| 201 |
|
| 202 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
scalar type name ([[expr.pseudo]]). Allowing this makes it possible to
|
| 204 |
write code without having to know if a destructor exists for a given
|
| 205 |
-
type. For example
|
| 206 |
|
| 207 |
``` cpp
|
| 208 |
typedef int I;
|
| 209 |
I* p;
|
| 210 |
p->I::~I();
|
| 211 |
```
|
| 212 |
|
|
|
|
|
|
|
|
|
| 1 |
## Destructors <a id="class.dtor">[[class.dtor]]</a>
|
| 2 |
|
| 3 |
+
In a declaration of a destructor, the *declarator* is a function
|
| 4 |
+
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:
|
|
|
|
| 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 |
The *class-name* shall not be a *typedef-name*. A destructor shall take
|
| 29 |
+
no arguments ([[dcl.fct]]). Each *decl-specifier* of the
|
| 30 |
+
*decl-specifier-seq* of a destructor declaration (if any) shall be
|
| 31 |
+
`friend`, `inline`, or `virtual`.
|
| 32 |
|
| 33 |
A destructor is used to destroy objects of its class type. The address
|
| 34 |
of a destructor shall not be taken. A destructor can be invoked for a
|
| 35 |
`const`, `volatile` or `const` `volatile` object. `const` and `volatile`
|
| 36 |
semantics ([[dcl.type.cv]]) are not applied on an object under
|
| 37 |
destruction. They stop being in effect when the destructor for the most
|
| 38 |
derived object ([[intro.object]]) starts.
|
| 39 |
|
| 40 |
+
[*Note 1*: A declaration of a destructor that does not have a
|
| 41 |
+
*noexcept-specifier* has the same exception specification as if had been
|
| 42 |
+
implicitly declared ([[except.spec]]). — *end note*]
|
| 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 |
|
|
|
|
| 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 ([[basic.def.odr]]) or when it is
|
| 71 |
+
explicitly defaulted after its first declaration.
|
|
|
|
| 72 |
|
| 73 |
Before the defaulted destructor for a class is implicitly defined, all
|
| 74 |
the non-user-provided destructors for its base classes and its
|
| 75 |
non-static data members shall have been implicitly defined.
|
| 76 |
|
| 77 |
After executing the body of the destructor and destroying any automatic
|
| 78 |
objects allocated within the body, a destructor for class `X` calls the
|
| 79 |
destructors for `X`’s direct non-variant non-static data members, the
|
| 80 |
+
destructors for `X`’s non-virtual direct base classes and, if `X` is the
|
| 81 |
+
type of the most derived class ([[class.base.init]]), its destructor
|
| 82 |
+
calls the destructors for `X`’s virtual base classes. All destructors
|
| 83 |
+
are called as if they were referenced with a qualified name, that is,
|
| 84 |
+
ignoring any possible virtual overriding destructors in more derived
|
| 85 |
+
classes. Bases and members are destroyed in the reverse order of the
|
| 86 |
+
completion of their constructor (see [[class.base.init]]). A `return`
|
| 87 |
+
statement ([[stmt.return]]) in a destructor might not directly return
|
| 88 |
+
to the caller; before transferring control to the caller, the
|
| 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]]) at program termination ([[basic.start.term]]),
|
|
|
|
| 107 |
[[basic.stc.thread]]) at thread exit,
|
| 108 |
- for a constructed object with automatic storage duration (
|
| 109 |
[[basic.stc.auto]]) when the block in which an object is created
|
| 110 |
exits ([[stmt.dcl]]),
|
| 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 is also invoked implicitly
|
| 116 |
through use of a *delete-expression* ([[expr.delete]]) for a
|
| 117 |
constructed object allocated by a *new-expression* ([[expr.new]]); the
|
| 118 |
+
context of the invocation is the *delete-expression*.
|
| 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 |
+
[[class.base.init]], and [[except.throw]]. A program is ill-formed if a
|
| 126 |
+
destructor that is potentially invoked is deleted or not accessible from
|
| 127 |
+
the context of the invocation.
|
| 128 |
|
| 129 |
At the point of definition of a virtual destructor (including an
|
| 130 |
implicit definition ([[class.copy]])), the non-array deallocation
|
| 131 |
+
function is determined as if for the expression `delete this` appearing
|
| 132 |
+
in a non-virtual destructor of the destructor’s class (see
|
| 133 |
+
[[expr.delete]]). If the lookup fails or if the deallocation function
|
| 134 |
+
has a deleted definition ([[dcl.fct.def]]), the program is ill-formed.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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]]). — *end note*]
|
| 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 ([[class.mfct]]); that is, if the
|
| 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
|
| 149 |
+
destructor; see [[expr.delete]]. — *end note*]
|
| 150 |
+
|
| 151 |
+
[*Example 1*:
|
| 152 |
|
| 153 |
``` cpp
|
| 154 |
struct B {
|
| 155 |
virtual ~B() { }
|
| 156 |
};
|
|
|
|
| 169 |
B_ptr->B_alias::~B(); // calls B's destructor
|
| 170 |
B_ptr->B_alias::~B_alias(); // calls B's destructor
|
| 171 |
}
|
| 172 |
```
|
| 173 |
|
| 174 |
+
— *end example*]
|
|
|
|
|
|
|
|
|
|
| 175 |
|
| 176 |
+
[*Note 6*: An explicit destructor call must always be written using a
|
| 177 |
+
member access operator ([[expr.ref]]) or a *qualified-id* (
|
| 178 |
+
[[expr.prim]]); in particular, the *unary-expression* `~X()` in a member
|
| 179 |
+
function is not an explicit destructor call (
|
| 180 |
+
[[expr.unary.op]]). — *end note*]
|
| 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
|
| 186 |
+
*new-expression*. Such use of explicit placement and destruction of
|
| 187 |
+
objects can be necessary to cope with dedicated hardware resources and
|
| 188 |
+
for writing memory management facilities. For example,
|
| 189 |
|
| 190 |
``` cpp
|
| 191 |
void* operator new(std::size_t, void* p) { return p; }
|
| 192 |
struct X {
|
| 193 |
X(int);
|
|
|
|
| 201 |
f(p);
|
| 202 |
p->X::~X(); // cleanup
|
| 203 |
}
|
| 204 |
```
|
| 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 ([[basic.life]]).
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
+
[*Example 2*: If the destructor for an automatic object is explicitly
|
| 213 |
+
invoked, and the block is subsequently left in a manner that would
|
| 214 |
+
ordinarily invoke implicit destruction of the object, the behavior is
|
| 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 ([[expr.pseudo]]). Allowing this makes it possible to
|
| 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 |
+
|