Init
This commit is contained in:
331
cppdraft/expr/delete.md
Normal file
331
cppdraft/expr/delete.md
Normal 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.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)
|
||||
Reference in New Issue
Block a user