From Jason Turner

[class.dtor]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. 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
- 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:
13
 
14
  - in a *member-declaration* that belongs to the *member-specification*
15
- of a class but is not a friend declaration ([[class.friend]]), the
16
- *id-expression* is `~`*class-name* and the *class-name* is the
17
- injected-class-name (Clause  [[class]]) of the immediately-enclosing
18
- class;
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
- 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
 
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 ([[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]]),
106
- - for a constructed object with thread storage duration (
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
@@ -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 ([[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
@@ -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 ([[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
 
 
 
 
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
+