This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

331
cppdraft/expr/delete.md Normal file
View File

@@ -0,0 +1,331 @@
[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)