8 Expressions [expr]

8.5 Compound expressions [expr.compound]

8.5.2 Unary expressions [expr.unary]

8.5.2.5 Delete [expr.delete]

The delete-expression operator destroys a most derived object or array created by a new-expression.
delete-expression:
	:: delete cast-expression
	:: delete [ ] cast-expression
The first alternative is a single-object delete expression, and the second is an array delete expression.
Whenever the delete keyword is immediately followed by empty square brackets, it shall be interpreted as the second alternative.81
The operand shall be of pointer to object type or of class type.
If of class type, the operand is contextually implicitly converted to a pointer to object type.82
The delete-expression's result has type void.
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.
If not, the behavior is undefined.
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.83
If not, the behavior is undefined.
[Note
:
This means that the syntax of the delete-expression must match the type of the object allocated by new, not the syntax of the new-expression.
end note
]
[Note
:
A pointer to a const type can be the operand of a delete-expression; it is not necessary to cast away the constness of the pointer expression before it is used as the operand of the delete-expression.
end note
]
In a single-object delete expression, if the static type of the object to be deleted is different from its dynamic type, 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.
The cast-expression in a delete-expression shall be evaluated exactly once.
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, 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 value of the operand of the delete-expression is not a null pointer value, then:
[Note
:
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.
[Note
:
An implementation provides default definitions of the global deallocation functions operator delete for non-arrays ([new.delete.single]) and operator delete[] for arrays ([new.delete.array]).
A C++ program can provide alternative definitions of these functions ([replacement.functions]), and/or class-specific versions ([class.free]).
end note
]
When the keyword delete in a delete-expression is preceded by the unary ​::​ operator, the deallocation function's name is looked up in global scope.
Otherwise, the lookup considers class-specific deallocation functions ([class.free]).
If no class-specific deallocation function is found, the deallocation function's name is looked up in global scope.
If deallocation function lookup finds more than one usual deallocation function, the function to be called is selected as follows:
  • 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 exactly one preferred function is found, that function is selected and the selection process terminates.
    If more than one preferred function is found, all non-preferred functions are eliminated from further consideration.
  • If the deallocation functions have class scope, the one without a parameter of type std​::​size_­t is selected.
  • If the type is complete and if, for the second alternative (delete array) 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.
  • Otherwise, it is unspecified whether a deallocation function with a parameter of type std​::​size_­t is selected.
When a delete-expression is executed, the selected deallocation function shall be called with the address of the most-derived object in a single-object delete expression, or the address of the object suitably adjusted for the array allocation overhead ([expr.new]) in an array delete expression, as its first argument.
If a deallocation function with a parameter of type std​::​align_­val_­t is used, the alignment of the type of the object to be deleted is passed as the corresponding argument.
If a deallocation function with a parameter of type std​::​size_­t is used, the size of the most-derived type, or of the array plus allocation overhead, respectively, is passed as the corresponding argument.84
[Note
:
If this results in a call to a usual deallocation function, and either the first argument was not the result of a prior call to a usual allocation function or the second argument was not the corresponding argument in said call, the behavior is undefined ([new.delete.single], [new.delete.array]).
end note
]
Access and ambiguity control are done for both the deallocation function and the destructor ([class.dtor], [class.free]).
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.
This implies that an object cannot be deleted using a pointer of type void* because void is not an object type.
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 the static type of the object to be deleted is complete and is different from the dynamic type, and the destructor is not virtual, the size might be incorrect, but that case is already undefined, as stated above.