[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)