From Jason Turner

[class.free]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpe3tay5nh/{from.md → to.md} +271 -18
tmp/tmpe3tay5nh/{from.md → to.md} RENAMED
@@ -15,32 +15,31 @@ struct D1 : B {
15
 
16
  Arena* ap;
17
  void foo(int i) {
18
  new (ap) D1; // calls B::operator new(std::size_t, Arena*)
19
  new D1[i]; // calls ::operator new[](std::size_t)
20
- new D1; // ill-formed: ::operator new(std::size_t) hidden
21
  }
22
  ```
23
 
24
  — *end example*]
25
 
26
- When an object is deleted with a *delete-expression* ([[expr.delete]]),
27
- a deallocation function (`operator delete()` for non-array objects or
28
  `operator delete[]()` for arrays) is (implicitly) called to reclaim the
29
- storage occupied by the object ([[basic.stc.dynamic.deallocation]]).
30
 
31
  Class-specific deallocation function lookup is a part of general
32
- deallocation function lookup ([[expr.delete]]) and occurs as follows.
33
- If the *delete-expression* is used to deallocate a class object whose
34
  static type has a virtual destructor, the deallocation function is the
35
  one selected at the point of definition of the dynamic type’s virtual
36
- destructor ([[class.dtor]]).[^3] Otherwise, if the *delete-expression*
37
- is used to deallocate an object of class `T` or array thereof, the
38
- static and dynamic types of the object shall be identical and the
39
  deallocation function’s name is looked up in the scope of `T`. If this
40
- lookup fails to find the name, general deallocation function lookup (
41
- [[expr.delete]]) continues. If the result of the lookup is ambiguous or
42
  inaccessible, or if the lookup selects a placement deallocation
43
  function, the program is ill-formed.
44
 
45
  Any deallocation function for a class `X` is a static member (even if
46
  not explicitly declared `static`).
@@ -67,12 +66,12 @@ cannot be virtual.
67
  [*Note 1*:
68
 
69
  However, when the *cast-expression* of a *delete-expression* refers to
70
  an object of class type, because the deallocation function actually
71
  called is looked up in the scope of the class that is the dynamic type
72
- of the object, if the destructor is virtual, the effect is the same. For
73
- example,
74
 
75
  ``` cpp
76
  struct B {
77
  virtual ~B();
78
  void operator delete(void*, std::size_t);
@@ -80,18 +79,31 @@ struct B {
80
 
81
  struct D : B {
82
  void operator delete(void*);
83
  };
84
 
 
 
 
 
 
 
 
 
 
85
  void f() {
86
  B* bp = new D;
87
  delete bp; // 1: uses D::operator delete(void*)
 
 
88
  }
89
  ```
90
 
91
- Here, storage for the non-array object of class `D` is deallocated by
92
- `D::operator delete()`, due to the virtual destructor.
 
 
93
 
94
  — *end note*]
95
 
96
  [*Note 2*:
97
 
@@ -122,12 +134,253 @@ void f(int i) {
122
  Access to the deallocation function is checked statically. Hence, even
123
  though a different one might actually be executed, the statically
124
  visible deallocation function is required to be accessible.
125
 
126
  [*Example 3*: For the call on line “// 1” above, if
127
- `B::operator delete()` had been `private`, the delete expression would
128
  have been ill-formed. — *end example*]
129
 
130
  [*Note 3*: If a deallocation function has no explicit
131
- *noexcept-specifier*, it has a non-throwing exception specification (
132
- [[except.spec]]). — *end note*]
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  Arena* ap;
17
  void foo(int i) {
18
  new (ap) D1; // calls B::operator new(std::size_t, Arena*)
19
  new D1[i]; // calls ::operator new[](std::size_t)
20
+ new D1; // error: ::operator new(std::size_t) hidden
21
  }
22
  ```
23
 
24
  — *end example*]
25
 
26
+ When an object is deleted with a *delete-expression* [[expr.delete]], a
27
+ deallocation function (`operator delete()` for non-array objects or
28
  `operator delete[]()` for arrays) is (implicitly) called to reclaim the
29
+ storage occupied by the object [[basic.stc.dynamic.deallocation]].
30
 
31
  Class-specific deallocation function lookup is a part of general
32
+ deallocation function lookup [[expr.delete]] and occurs as follows. If
33
+ the *delete-expression* is used to deallocate a class object whose
34
  static type has a virtual destructor, the deallocation function is the
35
  one selected at the point of definition of the dynamic type’s virtual
36
+ destructor [[class.dtor]].[^15] Otherwise, if the *delete-expression* is
37
+ used to deallocate an object of class `T` or array thereof, the
 
38
  deallocation function’s name is looked up in the scope of `T`. If this
39
+ lookup fails to find the name, general deallocation function lookup
40
+ [[expr.delete]] continues. If the result of the lookup is ambiguous or
41
  inaccessible, or if the lookup selects a placement deallocation
42
  function, the program is ill-formed.
43
 
44
  Any deallocation function for a class `X` is a static member (even if
45
  not explicitly declared `static`).
 
66
  [*Note 1*:
67
 
68
  However, when the *cast-expression* of a *delete-expression* refers to
69
  an object of class type, because the deallocation function actually
70
  called is looked up in the scope of the class that is the dynamic type
71
+ of the object if the destructor is virtual, the effect is the same in
72
+ that case. For example,
73
 
74
  ``` cpp
75
  struct B {
76
  virtual ~B();
77
  void operator delete(void*, std::size_t);
 
79
 
80
  struct D : B {
81
  void operator delete(void*);
82
  };
83
 
84
+ struct E : B {
85
+ void log_deletion();
86
+ void operator delete(E *p, std::destroying_delete_t) {
87
+ p->log_deletion();
88
+ p->~E();
89
+ ::operator delete(p);
90
+ }
91
+ };
92
+
93
  void f() {
94
  B* bp = new D;
95
  delete bp; // 1: uses D::operator delete(void*)
96
+ bp = new E;
97
+ delete bp; // 2: uses E::operator delete(E*, std::destroying_delete_t)
98
  }
99
  ```
100
 
101
+ Here, storage for the object of class `D` is deallocated by
102
+ `D::operator delete()`, and the object of class `E` is destroyed and its
103
+ storage is deallocated by `E::operator delete()`, due to the virtual
104
+ destructor.
105
 
106
  — *end note*]
107
 
108
  [*Note 2*:
109
 
 
134
  Access to the deallocation function is checked statically. Hence, even
135
  though a different one might actually be executed, the statically
136
  visible deallocation function is required to be accessible.
137
 
138
  [*Example 3*: For the call on line “// 1” above, if
139
+ `B::operator delete()` had been private, the delete expression would
140
  have been ill-formed. — *end example*]
141
 
142
  [*Note 3*: If a deallocation function has no explicit
143
+ *noexcept-specifier*, it has a non-throwing exception specification
144
+ [[except.spec]]. — *end note*]
145
 
146
+ <!-- Link reference definitions -->
147
+ [basic.compound]: basic.md#basic.compound
148
+ [basic.def]: basic.md#basic.def
149
+ [basic.def.odr]: basic.md#basic.def.odr
150
+ [basic.life]: basic.md#basic.life
151
+ [basic.link]: basic.md#basic.link
152
+ [basic.lookup]: basic.md#basic.lookup
153
+ [basic.lookup.elab]: basic.md#basic.lookup.elab
154
+ [basic.lookup.qual]: basic.md#basic.lookup.qual
155
+ [basic.lookup.unqual]: basic.md#basic.lookup.unqual
156
+ [basic.lval]: expr.md#basic.lval
157
+ [basic.scope]: basic.md#basic.scope
158
+ [basic.scope.class]: basic.md#basic.scope.class
159
+ [basic.scope.hiding]: basic.md#basic.scope.hiding
160
+ [basic.start.dynamic]: basic.md#basic.start.dynamic
161
+ [basic.start.static]: basic.md#basic.start.static
162
+ [basic.start.term]: basic.md#basic.start.term
163
+ [basic.stc]: basic.md#basic.stc
164
+ [basic.stc.auto]: basic.md#basic.stc.auto
165
+ [basic.stc.dynamic]: basic.md#basic.stc.dynamic
166
+ [basic.stc.dynamic.deallocation]: basic.md#basic.stc.dynamic.deallocation
167
+ [basic.stc.static]: basic.md#basic.stc.static
168
+ [basic.stc.thread]: basic.md#basic.stc.thread
169
+ [basic.type.qualifier]: basic.md#basic.type.qualifier
170
+ [basic.types]: basic.md#basic.types
171
+ [class]: #class
172
+ [class.abstract]: #class.abstract
173
+ [class.access]: #class.access
174
+ [class.access.base]: #class.access.base
175
+ [class.access.nest]: #class.access.nest
176
+ [class.access.spec]: #class.access.spec
177
+ [class.access.virt]: #class.access.virt
178
+ [class.base.init]: #class.base.init
179
+ [class.bit]: #class.bit
180
+ [class.cdtor]: #class.cdtor
181
+ [class.compare]: #class.compare
182
+ [class.compare.default]: #class.compare.default
183
+ [class.compare.secondary]: #class.compare.secondary
184
+ [class.conv]: #class.conv
185
+ [class.conv.ctor]: #class.conv.ctor
186
+ [class.conv.fct]: #class.conv.fct
187
+ [class.copy.assign]: #class.copy.assign
188
+ [class.copy.ctor]: #class.copy.ctor
189
+ [class.copy.elision]: #class.copy.elision
190
+ [class.ctor]: #class.ctor
191
+ [class.default.ctor]: #class.default.ctor
192
+ [class.derived]: #class.derived
193
+ [class.dtor]: #class.dtor
194
+ [class.eq]: #class.eq
195
+ [class.expl.init]: #class.expl.init
196
+ [class.free]: #class.free
197
+ [class.friend]: #class.friend
198
+ [class.inhctor.init]: #class.inhctor.init
199
+ [class.init]: #class.init
200
+ [class.local]: #class.local
201
+ [class.mem]: #class.mem
202
+ [class.member.lookup]: #class.member.lookup
203
+ [class.mfct]: #class.mfct
204
+ [class.mfct.non-static]: #class.mfct.non-static
205
+ [class.mi]: #class.mi
206
+ [class.name]: #class.name
207
+ [class.nest]: #class.nest
208
+ [class.nested.type]: #class.nested.type
209
+ [class.paths]: #class.paths
210
+ [class.pre]: #class.pre
211
+ [class.prop]: #class.prop
212
+ [class.protected]: #class.protected
213
+ [class.qual]: basic.md#class.qual
214
+ [class.spaceship]: #class.spaceship
215
+ [class.static]: #class.static
216
+ [class.static.data]: #class.static.data
217
+ [class.static.mfct]: #class.static.mfct
218
+ [class.temporary]: basic.md#class.temporary
219
+ [class.this]: #class.this
220
+ [class.union]: #class.union
221
+ [class.union.anon]: #class.union.anon
222
+ [class.virtual]: #class.virtual
223
+ [cmp.categories]: support.md#cmp.categories
224
+ [cmp.categories.pre]: support.md#cmp.categories.pre
225
+ [cmp.partialord]: support.md#cmp.partialord
226
+ [cmp.strongord]: support.md#cmp.strongord
227
+ [cmp.weakord]: support.md#cmp.weakord
228
+ [conv]: expr.md#conv
229
+ [conv.mem]: expr.md#conv.mem
230
+ [conv.ptr]: expr.md#conv.ptr
231
+ [conv.rval]: expr.md#conv.rval
232
+ [dcl.array]: dcl.md#dcl.array
233
+ [dcl.attr.nouniqueaddr]: dcl.md#dcl.attr.nouniqueaddr
234
+ [dcl.constexpr]: dcl.md#dcl.constexpr
235
+ [dcl.decl]: dcl.md#dcl.decl
236
+ [dcl.enum]: dcl.md#dcl.enum
237
+ [dcl.fct]: dcl.md#dcl.fct
238
+ [dcl.fct.def]: dcl.md#dcl.fct.def
239
+ [dcl.fct.def.coroutine]: dcl.md#dcl.fct.def.coroutine
240
+ [dcl.fct.def.delete]: dcl.md#dcl.fct.def.delete
241
+ [dcl.fct.def.general]: dcl.md#dcl.fct.def.general
242
+ [dcl.fct.default]: dcl.md#dcl.fct.default
243
+ [dcl.fct.spec]: dcl.md#dcl.fct.spec
244
+ [dcl.init]: dcl.md#dcl.init
245
+ [dcl.init.aggr]: dcl.md#dcl.init.aggr
246
+ [dcl.init.list]: dcl.md#dcl.init.list
247
+ [dcl.init.ref]: dcl.md#dcl.init.ref
248
+ [dcl.inline]: dcl.md#dcl.inline
249
+ [dcl.spec.auto]: dcl.md#dcl.spec.auto
250
+ [dcl.stc]: dcl.md#dcl.stc
251
+ [dcl.type.cv]: dcl.md#dcl.type.cv
252
+ [dcl.type.elab]: dcl.md#dcl.type.elab
253
+ [dcl.type.simple]: dcl.md#dcl.type.simple
254
+ [dcl.typedef]: dcl.md#dcl.typedef
255
+ [depr.impldec]: future.md#depr.impldec
256
+ [depr.static.constexpr]: future.md#depr.static.constexpr
257
+ [diff.class]: compatibility.md#diff.class
258
+ [except.ctor]: except.md#except.ctor
259
+ [except.handle]: except.md#except.handle
260
+ [except.pre]: except.md#except.pre
261
+ [except.spec]: except.md#except.spec
262
+ [except.throw]: except.md#except.throw
263
+ [expr.ass]: expr.md#expr.ass
264
+ [expr.call]: expr.md#expr.call
265
+ [expr.cast]: expr.md#expr.cast
266
+ [expr.const]: expr.md#expr.const
267
+ [expr.const.cast]: expr.md#expr.const.cast
268
+ [expr.delete]: expr.md#expr.delete
269
+ [expr.dynamic.cast]: expr.md#expr.dynamic.cast
270
+ [expr.eq]: expr.md#expr.eq
271
+ [expr.new]: expr.md#expr.new
272
+ [expr.prim.id]: expr.md#expr.prim.id
273
+ [expr.prim.id.dtor]: expr.md#expr.prim.id.dtor
274
+ [expr.prim.id.qual]: expr.md#expr.prim.id.qual
275
+ [expr.prim.this]: expr.md#expr.prim.this
276
+ [expr.ref]: expr.md#expr.ref
277
+ [expr.reinterpret.cast]: expr.md#expr.reinterpret.cast
278
+ [expr.rel]: expr.md#expr.rel
279
+ [expr.static.cast]: expr.md#expr.static.cast
280
+ [expr.sub]: expr.md#expr.sub
281
+ [expr.throw]: expr.md#expr.throw
282
+ [expr.type.conv]: expr.md#expr.type.conv
283
+ [expr.typeid]: expr.md#expr.typeid
284
+ [expr.unary.op]: expr.md#expr.unary.op
285
+ [intro.execution]: basic.md#intro.execution
286
+ [intro.object]: basic.md#intro.object
287
+ [namespace.def]: dcl.md#namespace.def
288
+ [namespace.memdef]: dcl.md#namespace.memdef
289
+ [namespace.udecl]: dcl.md#namespace.udecl
290
+ [over]: over.md#over
291
+ [over.ass]: over.md#over.ass
292
+ [over.best.ics]: over.md#over.best.ics
293
+ [over.binary]: over.md#over.binary
294
+ [over.ics.ref]: over.md#over.ics.ref
295
+ [over.load]: over.md#over.load
296
+ [over.match]: over.md#over.match
297
+ [over.match.best]: over.md#over.match.best
298
+ [over.match.call]: over.md#over.match.call
299
+ [over.match.copy]: over.md#over.match.copy
300
+ [over.match.funcs]: over.md#over.match.funcs
301
+ [over.oper]: over.md#over.oper
302
+ [over.over]: over.md#over.over
303
+ [special]: #special
304
+ [stmt.dcl]: stmt.md#stmt.dcl
305
+ [stmt.return]: stmt.md#stmt.return
306
+ [stmt.return.coroutine]: stmt.md#stmt.return.coroutine
307
+ [string.classes]: strings.md#string.classes
308
+ [temp.arg]: temp.md#temp.arg
309
+ [temp.class.spec]: temp.md#temp.class.spec
310
+ [temp.constr]: temp.md#temp.constr
311
+ [temp.constr.order]: temp.md#temp.constr.order
312
+ [temp.dep.type]: temp.md#temp.dep.type
313
+ [temp.expl.spec]: temp.md#temp.expl.spec
314
+ [temp.friend]: temp.md#temp.friend
315
+ [temp.inst]: temp.md#temp.inst
316
+ [temp.mem]: temp.md#temp.mem
317
+ [temp.param]: temp.md#temp.param
318
+ [temp.pre]: temp.md#temp.pre
319
+ [temp.spec]: temp.md#temp.spec
320
+ [temp.variadic]: temp.md#temp.variadic
321
+
322
+ [^1]: This ensures that two subobjects that have the same class type and
323
+ that belong to the same most derived object are not allocated at the
324
+ same address [[expr.eq]].
325
+
326
+ [^2]: See, for example, `<cstring>`.
327
+
328
+ [^3]: This implies that the reference parameter of the
329
+ implicitly-declared copy constructor cannot bind to a `volatile`
330
+ lvalue; see  [[diff.class]].
331
+
332
+ [^4]: Because a template assignment operator or an assignment operator
333
+ taking an rvalue reference parameter is never a copy assignment
334
+ operator, the presence of such an assignment operator does not
335
+ suppress the implicit declaration of a copy assignment operator.
336
+ Such assignment operators participate in overload resolution with
337
+ other assignment operators, including copy assignment operators,
338
+ and, if selected, will be used to assign an object.
339
+
340
+ [^5]: This implies that the reference parameter of the
341
+ implicitly-declared copy assignment operator cannot bind to a
342
+ `volatile` lvalue; see  [[diff.class]].
343
+
344
+ [^6]: These conversions are considered as standard conversions for the
345
+ purposes of overload resolution ([[over.best.ics]],
346
+ [[over.ics.ref]]) and therefore initialization [[dcl.init]] and
347
+ explicit casts [[expr.static.cast]]. A conversion to `void` does not
348
+ invoke any conversion function [[expr.static.cast]]. Even though
349
+ never directly called to perform a conversion, such conversion
350
+ functions can be declared and can potentially be reached through a
351
+ call to a virtual conversion function in a base class.
352
+
353
+ [^7]: The use of the `virtual` specifier in the declaration of an
354
+ overriding function is valid but redundant (has empty semantics).
355
+
356
+ [^8]: If all virtual functions are immediate functions, the class is
357
+ still polymorphic even though its internal representation might not
358
+ otherwise require any additions for that polymorphic behavior.
359
+
360
+ [^9]: A function with the same name but a different parameter list
361
+ [[over]] as a virtual function is not necessarily virtual and does
362
+ not override. Access control [[class.access]] is not considered in
363
+ determining overriding.
364
+
365
+ [^10]: Multi-level pointers to classes or references to multi-level
366
+ pointers to classes are not allowed.
367
+
368
+ [^11]: Access permissions are thus transitive and cumulative to nested
369
+ and local classes.
370
+
371
+ [^12]: As specified previously in [[class.access]], private members of a
372
+ base class remain inaccessible even to derived classes unless friend
373
+ declarations within the base class definition are used to grant
374
+ access explicitly.
375
+
376
+ [^13]: This additional check does not apply to other members, e.g.,
377
+ static data members or enumerator member constants.
378
+
379
+ [^14]: Because only one object is destroyed instead of two, and one
380
+ copy/move constructor is not executed, there is still one object
381
+ destroyed for each one constructed.
382
+
383
+ [^15]: A similar provision is not needed for the array version of
384
+ `operator` `delete` because  [[expr.delete]] requires that in this
385
+ situation, the static type of the object to be deleted be the same
386
+ as its dynamic type.