[expr.delete]

# 7 Expressions [[expr]](./#expr)

## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.delete)

### 7.6.2 Unary expressions [[expr.unary]](expr.unary#expr.delete)

#### 7.6.2.9 Delete [expr.delete]

[1](#1)

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

The [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") operator destroys a[most derived object](intro.object#def:most_derived_object "6.8.2 Object model [intro.object]") or array created by a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")[.](#1.sentence-1)

[delete-expression:](#nt:delete-expression "7.6.2.9 Delete [expr.delete]")  
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")  
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")

The first alternative is a[*single-object delete expression*](#def:delete,single-object "7.6.2.9 Delete [expr.delete]"), and the
second is an [*array delete expression*](#def:delete,array "7.6.2.9 Delete [expr.delete]")[.](#1.sentence-2)

Whenever the delete keyword is immediately followed by empty square
brackets, it shall be interpreted as the second alternative[.](#1.sentence-3)[61](#footnote-61 "A lambda-expression with a lambda-introducer that consists of empty square brackets can follow the delete keyword if the lambda-expression is enclosed in parentheses.")

If the operand is of
class type, it is contextually implicitly converted ([[conv]](conv "7.3 Standard conversions"))
to a pointer to object
type
and the converted operand is used in place of the original operand
for the remainder of this subclause[.](#1.sentence-4)

Otherwise, it shall be a prvalue of pointer to object type[.](#1.sentence-5)

The [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") has typevoid[.](#1.sentence-6)

[2](#2)

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

In a single-object delete expression, the value of the operand ofdelete may be a null pointer value,
a pointer value
that resulted from a previous non-array [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]"), or
a pointer to a base class subobject
of an object created by such a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")[.](#2.sentence-1)

If not, the behavior is undefined[.](#2.sentence-2)

In an array delete expression, the value of the operand of delete may be a null pointer value or a pointer value that resulted from
a previous array [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") whose
allocation function was not a non-allocating form ([[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms"))[.](#2.sentence-3)[62](#footnote-62 "For nonzero-length arrays, this is the same as a pointer to the first element of the array created by that new-expression. Zero-length arrays do not have a first element.")

If not, the behavior is undefined[.](#2.sentence-4)

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

This means that the syntax of the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") must
match the type of the object allocated by new, not the syntax of the[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")[.](#2.sentence-5)

â *end note*]

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

A pointer to a const type can be the operand of a[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]"); it is not necessary to cast away the
constness ([[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast")) of the pointer expression before it is
used as the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]")[.](#2.sentence-6)

â *end note*]

[3](#3)

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

In a single-object delete expression, if the static type of the object to be
deleted is not similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) to its dynamic type
and the selected deallocation function (see below)
is not a destroying operator delete,
the static type shall be a base
class of the dynamic type of the object to be deleted and the static type shall
have a virtual destructor or the behavior is undefined[.](#3.sentence-1)

In an array delete
expression, if the dynamic type of the object to be deleted is not similar to
its static type, the behavior is undefined[.](#3.sentence-2)

[4](#4)

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

If the object being deleted has incomplete class type at the point of deletion,
the program is ill-formed[.](#4.sentence-1)

[5](#5)

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

If the value of the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") is not a
null pointer value
and the selected deallocation function (see below)
is not a destroying operator delete,
evaluating the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") invokes the
destructor (if any) for the object or the elements of the array being
deleted[.](#5.sentence-1)

The destructor shall be accessible from the point where
the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") appears[.](#5.sentence-2)

In the case of an array, the elements are destroyed in
order of decreasing address (that is, in reverse order of the completion
of their constructor; see [[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#5.sentence-3)

[6](#6)

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

If the value of the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") is not a
null pointer value, then:

- [(6.1)](#6.1)

  If the allocation call for the [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") for the object to
be deleted was not omitted and the allocation was not extended ([[expr.new]](expr.new "7.6.2.8 New")), the[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") shall call a [deallocation
function](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]")[.](#6.1.sentence-1)
  The value returned from the
allocation call of the [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") shall be passed as the
first argument to the deallocation function[.](#6.1.sentence-2)

- [(6.2)](#6.2)

  Otherwise, if the allocation was extended or was provided by extending the
allocation of another [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]"), and the[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") for every other pointer value produced by a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") that had storage provided by the extended[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") has been evaluated, the[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") shall call a deallocation function[.](#6.2.sentence-1)
  The value
returned from the allocation call of the extended [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") shall be passed as the first argument to the deallocation function[.](#6.2.sentence-2)

- [(6.3)](#6.3)

  Otherwise, the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") will not call a
deallocation function[.](#6.3.sentence-1)

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

The deallocation function is called regardless of whether the destructor
for the object or some element of the array throws an exception[.](#6.sentence-2)

â *end note*]

If the value of the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") is a
null pointer value, it is unspecified whether a deallocation function will be
called as described above[.](#6.sentence-3)

[7](#7)

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

If a deallocation function is called,
it is operator delete for a single-object delete expression oroperator delete[] for an array delete expression[.](#7.sentence-1)

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

An implementation provides default definitions of the global
deallocation functions ([[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"))[.](#7.sentence-2)

A C++ program can provide alternative definitions of these
functions ([[replacement.functions]](replacement.functions "16.4.5.6 Replacement functions")), and/or class-specific
versions ([[class.free]](class.free "11.4.11 Allocation and deallocation functions"))[.](#7.sentence-3)

â *end note*]

[8](#8)

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

If the keyword delete in a [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") is not preceded by the unary ​::​ operator and the type of the operand is
a pointer to a (possibly cv-qualified) class type T or (possibly multidimensional) array thereof:

- [(8.1)](#8.1)

  For a single-object delete expression,
if the operand is a pointer to cv T andT has a virtual destructor,
the deallocation function is the one selected at the point of definition of
the dynamic type's virtual destructor ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#8.1.sentence-1)

- [(8.2)](#8.2)

  Otherwise,
a search is performed for the deallocation function's name
in the scope of T[.](#8.2.sentence-1)

Otherwise, or if nothing is found,
the deallocation function's name is looked up by
searching for it in the global scope[.](#8.sentence-2)

In any case, any declarations
other than of usual deallocation functions ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions"))
are discarded[.](#8.sentence-3)

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

If only a placement deallocation function is found in a class,
the program is ill-formed because the lookup set is empty ([[basic.lookup]](basic.lookup "6.5 Name lookup"))[.](#8.sentence-4)

â *end note*]

[9](#9)

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

The deallocation function to be called is selected as follows:

- [(9.1)](#9.1)

  If any of the deallocation functions is a destroying operator delete,
all deallocation functions that are not destroying operator deletes
are eliminated from further consideration[.](#9.1.sentence-1)

- [(9.2)](#9.2)

  If the type has new-extended alignment,
a function with a parameter of type std​::​align_val_t is preferred;
otherwise a function without such a parameter is preferred[.](#9.2.sentence-1)
  If any preferred functions are found,
all non-preferred functions are eliminated from further consideration[.](#9.2.sentence-2)

- [(9.3)](#9.3)

  If exactly one function remains,
that function is selected and the selection process terminates[.](#9.3.sentence-1)

- [(9.4)](#9.4)

  If the deallocation functions belong to a class scope,
the one without a parameter of type std​::​size_t is selected[.](#9.4.sentence-1)

- [(9.5)](#9.5)

  If the type is complete
and if, for an array delete expression only,
the operand is a pointer to a class type with a
non-trivial destructor or a (possibly multidimensional) array thereof,
the function with a parameter of type std​::​size_t is selected[.](#9.5.sentence-1)

- [(9.6)](#9.6)

  Otherwise, it is unspecified
whether a deallocation function with a parameter of type std​::​size_t is selected[.](#9.6.sentence-1)

Unless the deallocation function is selected
at the point of definition of the dynamic type's virtual destructor,
the selected deallocation function shall be accessible
from the point where the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") appears[.](#9.sentence-2)

[10](#10)

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

For a single-object delete expression,
the deleted object is
the object A pointed to by the operand
if the static type of A does not have a virtual destructor,
and the most-derived object of A otherwise[.](#10.sentence-1)

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

If the deallocation function is not a destroying operator delete
and the deleted object is not the most derived object in the former case,
the behavior is undefined,
as stated above[.](#10.sentence-2)

â *end note*]

For an array delete expression,
the deleted object is
the array object[.](#10.sentence-3)

When a [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") is executed, the selected deallocation function shall be called with
the address of the deleted object
in a single-object delete expression, or
the address of the deleted object
suitably adjusted for the array allocation
overhead ([[expr.new]](expr.new "7.6.2.8 New")) in an array delete expression,
as its first argument[.](#10.sentence-4)

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

Any cv-qualifiers in the type of the deleted object
are ignored when forming this argument[.](#10.sentence-5)

â *end note*]

If a destroying operator delete is used,
an unspecified value
is passed as the argument
corresponding to the parameter of type std​::​destroying_delete_t[.](#10.sentence-6)

If a deallocation function
with a parameter of type std​::​align_val_t is used,
the alignment of the type of the deleted object
is passed as the corresponding argument[.](#10.sentence-7)

If a deallocation function
with a parameter of type std​::​size_t is used,
the size of the deleted object
in a single-object delete expression, or
of the array plus allocation overhead
in an array delete expression,
is passed as the corresponding argument[.](#10.sentence-8)

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

If this results in a call to a replaceable deallocation function,
and either
the first argument was not the result of
a prior call to a replaceable allocation function or
the second or third argument was not the corresponding argument in said call,
the behavior is undefined ([[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"))[.](#10.sentence-9)

â *end note*]

[61)](#footnote-61)[61)](#footnoteref-61)

A[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") with a [*lambda-introducer*](expr.prim.lambda.general#nt:lambda-introducer "7.5.6.1 General [expr.prim.lambda.general]") that consists of empty square brackets can follow the delete keyword
if the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") is enclosed in parentheses[.](#footnote-61.sentence-1)

[62)](#footnote-62)[62)](#footnoteref-62)

For nonzero-length
arrays, this is the same as a pointer to the first
element of the array created by that [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")[.](#footnote-62.sentence-1)

Zero-length arrays do not have a first element[.](#footnote-62.sentence-2)
