Files
2025-10-25 03:02:53 +03:00

332 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.9Delete[expr.delete]") operator destroys a[most derived object](intro.object#def:most_derived_object "6.8.2Object model[intro.object]") or array created by a[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")[.](#1.sentence-1)
[delete-expression:](#nt:delete-expression "7.6.2.9Delete[expr.delete]")
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
The first alternative is a[*single-object delete expression*](#def:delete,single-object "7.6.2.9Delete[expr.delete]"), and the
second is an [*array delete expression*](#def:delete,array "7.6.2.9Delete[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.3Standard 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.9Delete[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.8New[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.8New[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.8New[expr.new]") whose
allocation function was not a non-allocating form ([[new.delete.placement]](new.delete.placement "17.6.3.4Non-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.9Delete[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.8New[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.9Delete[expr.delete]"); it is not necessary to cast away the
constness ([[expr.const.cast]](expr.const.cast "7.6.1.11Const cast")) of the pointer expression before it is
used as the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[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.6Qualification 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.9Delete[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.9Delete[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.9Delete[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.3Initializing 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.9Delete[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.8New[expr.new]") for the object to
be deleted was not omitted and the allocation was not extended ([[expr.new]](expr.new "7.6.2.8New")), the[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") shall call a [deallocation
function](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation 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.8New[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.8New[expr.new]"), and the[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") for every other pointer value produced by a[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") that had storage provided by the extended[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") has been evaluated, the[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[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.8New[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.9Delete[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.9Delete[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.2Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3Array forms"))[.](#7.sentence-2)
A C++ program can provide alternative definitions of these
functions ([[replacement.functions]](replacement.functions "16.4.5.6Replacement functions")), and/or class-specific
versions ([[class.free]](class.free "11.4.11Allocation 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.9Delete[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.7Destructors"))[.](#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.3Deallocation 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.5Name 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.9Delete[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.9Delete[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.8New")) 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.2Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3Array 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.1General[expr.prim.lambda.general]") with a [*lambda-introducer*](expr.prim.lambda.general#nt:lambda-introducer "7.5.6.1General[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.1General[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.8New[expr.new]")[.](#footnote-62.sentence-1)
Zero-length arrays do not have a first element[.](#footnote-62.sentence-2)