[class.dtor]

# 11 Classes [[class]](./#class)

## 11.4 Class members [[class.mem]](class.mem#class.dtor)

### 11.4.7 Destructors [class.dtor]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2082)

A declaration whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") has an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") that begins with a ~ declares a [*prospective destructor*](#def:destructor,prospective "11.4.7 Destructors [class.dtor]");
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") shall be a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the form

[*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt

where the [*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") consists solely of an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"), an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
and optional surrounding parentheses, and the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") has
one of the following forms:

- [(1.1)](#1.1)

in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") that belongs to the[*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of a class or class template
but is not a friend
declaration ([[class.friend]](class.friend "11.8.4 Friends")), the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is~[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") and the [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") is the
injected-class-name ([[class.pre]](class.pre "11.1 Preamble")) of the immediately-enclosing entity or

- [(1.2)](#1.2)

otherwise, the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")~[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") and the [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") is the injected-class-name of the
class nominated by the [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#1.sentence-1)

A prospective destructor shall take no arguments ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#1.sentence-2)

Each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a prospective destructor declaration (if any)
shall befriend,inline,virtual, orconstexpr[.](#1.sentence-3)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2120)

If a class has no user-declared
prospective destructor,
a prospective destructor is implicitly
declared as defaulted ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions"))[.](#2.sentence-1)

An implicitly-declared prospective destructor is an
inline public member of its class[.](#2.sentence-2)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2130)

An implicitly-declared prospective destructor for a class X will have the form~X()

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2136)

At the end of the definition of a class,
overload resolution is performed
among the prospective destructors declared in that class
with an empty argument list
to select the [*destructor*](#def:destructor "11.4.7 Destructors [class.dtor]") for the class,
also known as the [*selected destructor*](#def:destructor,selected "11.4.7 Destructors [class.dtor]")[.](#4.sentence-1)

The program is ill-formed if overload resolution fails[.](#4.sentence-2)

Destructor selection does not constitute
a reference to,
or odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) of,
the selected destructor,
and in particular,
the selected destructor may be deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3 Deleted definitions"))[.](#4.sentence-3)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2151)

The address of a destructor shall not be taken[.](#5.sentence-1)

[*Note [1](#note-1)*:

A return statement in the body of a destructor
cannot specify a return value ([[stmt.return]](stmt.return "8.8.4 The return statement"))[.](#5.sentence-2)

â *end note*]

A destructor can be invoked for aconst,volatile orconstvolatile object[.](#5.sentence-3)

const andvolatile semantics ([[dcl.type.cv]](dcl.type.cv "9.2.9.2 The cv-qualifiers")) are not applied on an object under destruction[.](#5.sentence-4)

They stop being in effect when the destructor for the
most derived object ([[intro.object]](intro.object "6.8.2 Object model")) starts[.](#5.sentence-5)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2175)

[*Note [2](#note-2)*:

A declaration of a destructor that does not have a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") has the same exception specification as if it had been implicitly declared ([[except.spec]](except.spec "14.5 Exception specifications"))[.](#6.sentence-1)

â *end note*]

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2181)

A defaulted destructor for a class X is defined as deleted if

- [(7.1)](#7.1)

X is a non-union class and
 any non-variant potentially constructed subobject has class type M (or possibly multidimensional array thereof) where M has a destructor that is deleted or
 is inaccessible from the defaulted destructor,

- [(7.2)](#7.2)

X is a union and
  * [(7.2.1)](#7.2.1)

overload resolution to select a constructor to
 default-initialize an object of type X either fails or
 selects a constructor that is either deleted or not trivial, or

  * [(7.2.2)](#7.2.2)

X has a variant member V of
 class type M (or possibly multi-dimensional array thereof)
 where V has a default member initializer and M has a destructor that is non-trivial, or,

- [(7.3)](#7.3)

for a virtual destructor, lookup of the non-array deallocation
 function results in an ambiguity or in a function that is deleted or
 inaccessible from the defaulted destructor[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2210)

A destructor for a class X is trivial if it is not user-provided and if

- [(8.1)](#8.1)

the destructor is not virtual,

- [(8.2)](#8.2)

all of the direct base classes of X have trivial destructors, and

- [(8.3)](#8.3)

either X is a union or
for all of the non-variant non-static data members of X that are of class
type (or array thereof), each such class has a trivial destructor[.](#8.sentence-1)

Otherwise, the destructor is[*non-trivial*](#def:destructor,non-trivial "11.4.7 Destructors [class.dtor]")[.](#8.sentence-2)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2225)

A defaulted destructor is a constexpr destructor
if it is constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"))[.](#9.sentence-1)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2229)

Before a
defaulted destructor for a class is implicitly defined, all the non-user-provided
destructors for its base classes and its non-static data members are
implicitly defined[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2235)

A prospective destructor can be
declared virtual ([[class.virtual]](class.virtual "11.7.3 Virtual functions"))
and with a [*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1 General [class.mem.general]") ([[class.abstract]](class.abstract "11.7.4 Abstract classes"))[.](#11.sentence-1)

If the destructor of a class is virtual and
any objects of that class or any derived class are created in the program,
the destructor shall be defined[.](#11.sentence-2)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2245)

[*Note [3](#note-3)*:

Some language constructs have special semantics when used during destruction;
see [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction")[.](#12.sentence-1)

â *end note*]

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2252)

After executing the body of the destructor and destroying
any objects with automatic storage duration allocated within the body, a
destructor for classX calls the destructors forX's
direct non-variant non-static data members other than anonymous unions,
the destructors forX's
non-virtual direct base classes and, ifX is the most derived class ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")),
its destructor calls the destructors forX's
virtual base classes[.](#13.sentence-1)

All destructors are called as if they were referenced with a qualified name,
that is, ignoring any possible virtual overriding destructors in more
derived classes[.](#13.sentence-2)

Bases and members are destroyed in the reverse order of the completion of
their constructor (see [[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#13.sentence-3)

[*Note [4](#note-4)*:

Areturn statement ([[stmt.return]](stmt.return "8.8.4 The return statement")) in a destructor might not directly return to the
caller; before transferring control to the caller, the destructors for the
members and bases are called[.](#13.sentence-4)

â *end note*]

Destructors for elements of an array are called in reverse order of their
construction (see [[class.init]](class.init "11.9 Initialization"))[.](#13.sentence-5)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2287)

A destructor is invoked implicitly

- [(14.1)](#14.1)

for a constructed object with static storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")) at program termination ([[basic.start.term]](basic.start.term "6.10.3.4 Termination")),

- [(14.2)](#14.2)

for a constructed object with thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration")) at thread exit,

- [(14.3)](#14.3)

for a constructed object with automatic storage duration ([[basic.stc.auto]](basic.stc.auto "6.8.6.4 Automatic storage duration")) when the block in which an object is created exits ([[stmt.dcl]](stmt.dcl "8.10 Declaration statement")),

- [(14.4)](#14.4)

for a constructed temporary object when its lifetime ends ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion"), [[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#14.sentence-1)

In each case, the context of the invocation is the context of the construction of
the object[.](#14.sentence-2)

A destructor may also be invoked implicitly through use of a[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]") ([[expr.delete]](expr.delete "7.6.2.9 Delete")) for a constructed object allocated
by a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")); the context of the invocation is the[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]")[.](#14.sentence-3)

[*Note [5](#note-5)*:

An array of class type contains several subobjects for each of which
the destructor is invoked[.](#14.sentence-4)

â *end note*]

A destructor can also be invoked explicitly[.](#14.sentence-5)

A destructor is [*potentially invoked*](#def:potentially_invoked "11.4.7 Destructors [class.dtor]") if it is invoked or as specified in [[expr.new]](expr.new "7.6.2.8 New"),[[stmt.return]](stmt.return "8.8.4 The return statement"), [[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates"),[[class.base.init]](class.base.init "11.9.3 Initializing bases and members"), and [[except.throw]](except.throw "14.2 Throwing an exception")[.](#14.sentence-6)

A program is ill-formed if a destructor that is potentially invoked is deleted
or not accessible from the context of the invocation[.](#14.sentence-7)

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2319)

At the point of definition of a virtual destructor (including an implicit
definition), the non-array deallocation function is
determined as if for the expression delete this appearing in a
non-virtual destructor of the destructor's class (see [[expr.delete]](expr.delete "7.6.2.9 Delete"))[.](#15.sentence-1)

If the lookup fails or if the deallocation function has
a deleted definition ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions")), the program is ill-formed[.](#15.sentence-2)

[*Note [6](#note-6)*:

This assures that a deallocation function corresponding to the dynamic type of an
object is available for the[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]") ([[class.free]](class.free "11.4.11 Allocation and deallocation functions"))[.](#15.sentence-3)

â *end note*]

[16](#16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2332)

In an explicit destructor call, the destructor is specified by a~ followed by a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") that denotes the destructor's class type[.](#16.sentence-1)

The invocation of a destructor is subject to the usual rules for member
functions ([[class.mfct]](class.mfct "11.4.2 Member functions"));
that is, if the object is not of the destructor's class type and
not of a class derived from the destructor's class type (including when
the destructor is invoked via a null pointer value), the program has
undefined behavior[.](#16.sentence-2)

[*Note [7](#note-7)*:

Invoking delete on a null pointer does not call the
destructor; see [[expr.delete]](expr.delete "7.6.2.9 Delete")[.](#16.sentence-3)

â *end note*]

[*Example [1](#example-1)*: struct B {virtual ~B() { }};struct D : B {~D() { }};

D D_object;typedef B B_alias;
B* B_ptr = &D_object;

void f() { D_object.B::~B(); // calls B's destructor B_ptr->~B(); // calls D's destructor B_ptr->~B_alias(); // calls D's destructor B_ptr->B_alias::~B(); // calls B's destructor B_ptr->B_alias::~B_alias(); // calls B's destructor} â *end example*]

[*Note [8](#note-8)*:

An explicit destructor call must always be written using
a member access operator ([[expr.ref]](expr.ref "7.6.1.5 Class member access")) or a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified names"));
in particular, the[*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")~X() in a member function is not an explicit destructor call ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators"))[.](#16.sentence-4)

â *end note*]

[17](#17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2380)

[*Note [9](#note-9)*:

Explicit calls of destructors are rarely needed[.](#17.sentence-1)

One use of such calls is for objects placed at specific
addresses using a placement[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")[.](#17.sentence-2)

Such use of explicit placement and destruction of objects can be necessary
to cope with dedicated hardware resources and for writing memory management
facilities[.](#17.sentence-3)

[*Example [2](#example-2)*: void* operator new(std::size_t, void* p) { return p; }struct X { X(int); ~X();};void f(X* p);

void g() { // rare, specialized use:char* buf = new char[sizeof(X)];
 X* p = new(buf) X(222); // use buf[] and initialize f(p);
 p->X::~X(); // cleanup} â *end example*]

â *end note*]

[18](#18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2409)

Once a destructor is invoked for an object, the object's lifetime ends;
the behavior is undefined if the destructor is invoked
for an object whose lifetime has ended ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#18.sentence-1)

[*Example [3](#example-3)*:

If the destructor for an object with automatic storage duration is explicitly invoked,
and the block is subsequently left in a manner that would ordinarily
invoke implicit destruction of the object, the behavior is undefined[.](#18.sentence-2)

â *end example*]

[19](#19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2419)

[*Note [10](#note-10)*:

The notation for explicit call of a destructor can be used for any scalar type
name ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5 Destruction"))[.](#19.sentence-1)

Allowing this makes it possible to write code without having to know if a
destructor exists for a given type[.](#19.sentence-2)

For example:typedef int I;
I* p;
p->I::~I();

â *end note*]

[20](#20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2434)

A destructor shall not be a coroutine[.](#20.sentence-1)
