If the operand has a class type, the operand is converted to a pointer
type by calling the above-mentioned conversion function, and the
converted operand is used in place of the original operand for the
remainder of this subclause.
In a single-object delete expression, the value of the operand of
delete may be a null pointer value, a pointer to a non-array object
created by a previous new-expression,
or a pointer to a
subobject representing a
base class of such an
object.
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.74
In a single-object delete expression, if the static type of the object to be
deleted is different from 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.
In an array delete
expression, if the dynamic type of the object to be deleted differs from its
static type, the behavior is undefined.
If the object being deleted has incomplete class type at the point of
deletion and the complete class has a non-trivial destructor or a
deallocation function, the behavior is undefined.
If the value of the operand of the delete-expression is not a
null pointer value
and the selected deallocation function (see below)
is not a destroying operator delete,
the delete-expression will invoke the
destructor (if any) for the object or the elements of the array being
deleted.
In the case of an array, the elements will be destroyed in
order of decreasing address (that is, in reverse order of the completion
of their constructor; see [class.base.init]).
If the allocation call for the new-expression for the object to
be deleted was not omitted and the allocation was not extended ([expr.new]), the
delete-expression shall call a deallocation
function. The value returned from the
allocation call of the new-expression shall be passed as the
first argument to the deallocation function.
Otherwise, if the allocation was extended or was provided by extending the
allocation of another new-expression, and the
delete-expression for every other pointer value produced by a
new-expression that had storage provided by the extended
new-expression has been evaluated, the
delete-expression shall call a deallocation function. The value
returned from the allocation call of the extended new-expression
shall be passed as the first argument to the deallocation function.
The deallocation function is called regardless of whether the destructor
for the object or some element of the array throws an exception.
— end note
]
If the value of the operand of the delete-expression is a
null pointer value, it is unspecified whether a deallocation function will be
called as described above.
An implementation provides default definitions of the global
deallocation functions operatordelete for
non-arrays ([new.delete.single]) and
operatordelete[] for arrays ([new.delete.array]).
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.
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. If any preferred functions are found,
all non-preferred functions are eliminated from further consideration.
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 multi-dimensional) array thereof,
the function with a parameter of type std::size_t is selected.
For a single-object delete expression,
the deleted object is
the object denoted by the operand
if its static type does not have a virtual destructor,
and its most-derived object otherwise.
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.
— end note
]
For an array delete expression,
the deleted object is
the array object.
When a delete-expression
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]) in an array delete expression,
as its first argument.
Any cv-qualifiers in the type of the deleted object
are ignored when forming this argument.
— 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.
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.
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.
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.array]).