Defined in header
Replaceable usual deallocation functions
voidoperatordelete(void*ptr)throw(); (1)(until C++11)voidoperatordelete(void*ptr)noexcept;(since C++11)voidoperatordelete[](void*ptr)throw(); (2)(until C++11)voidoperatordelete[](void*ptr)noexcept;(since C++11)voidoperatordelete(void*ptr,std::align_val_tal)noexcept; (3)(since C++17)voidoperatordelete[](void*ptr,std::align_val_tal)noexcept; (4)(since C++17)voidoperatordelete(void*ptr,std::size_tsz)noexcept; (5)(since C++14)voidoperatordelete[](void*ptr,std::size_tsz)noexcept; (6)(since C++14)voidoperatordelete(void*ptr,std::size_tsz,std::align_val_tal)noexcept; (7)(since C++17)voidoperatordelete[](void*ptr,std::size_tsz,std::align_val_tal)noexcept; (8)(since C++17)Replaceable placement deallocation functions
voidoperatordelete(void*ptr,conststd::nothrow_t&tag)throw(); (9)(until C++11)voidoperatordelete(void*ptr,conststd::nothrow_t&tag)noexcept;(since C++11)voidoperatordelete[](void*ptr,conststd::nothrow_t&tag)throw(); (10)(until C++11)voidoperatordelete[](void*ptr,conststd::nothrow_t&tag)noexcept;(since C++11)voidoperatordelete(void*ptr,std::align_val_tal,conststd::nothrow_t&tag)noexcept; (11)(since C++17)voidoperatordelete[](void*ptr,std::align_val_tal,conststd::nothrow_t&tag)noexcept; (12)(since C++17)Non-allocating placement deallocation functions
voidoperatordelete(void*ptr,void*place)throw(); (13)(until C++11)voidoperatordelete(void*ptr,void*place)noexcept;(since C++11)voidoperatordelete[](void*ptr,void*place)throw(); (14)(until C++11)voidoperatordelete[](void*ptr,void*place)noexcept;(since C++11)User-defined placement deallocation functions
voidoperatordelete(void*ptr,args...); (15)voidoperatordelete[](void*ptr,args...); (16)Class-specific usual deallocation functions
voidT::operatordelete(void*ptr); (17)voidT::operatordelete[](void*ptr); (18)voidT::operatordelete(void*ptr,std::align_val_tal); (19)(since C++17)voidT::operatordelete[](void*ptr,std::align_val_tal); (20)(since C++17)voidT::operatordelete(void*ptr,std::size_tsz); (21)voidT::operatordelete[](void*ptr,std::size_tsz); (22)voidT::operatordelete(void*ptr,std::size_tsz,std::align_val_tal); (23)(since C++17)voidT::operatordelete[](void*ptr,std::size_tsz,std::align_val_tal); (24)(since C++17)Class-specific placement deallocation functions
voidT::operatordelete(void*ptr,args...); (25)voidT::operatordelete[](void*ptr,args...); (26)Class-specific usual destroying deallocation functions
voidT::operatordelete(T*ptr,std::destroying_delete_t); (27)(since C++20)voidT::operatordelete(T*ptr,std::destroying_delete_t,std::align_val_tal); (28)(since C++20)voidT::operatordelete(T*ptr,std::destroying_delete_t,std::size_tsz); (29)(since C++20)voidT::operatordelete(T*ptr,std::destroying_delete_t,std::size_tsz,std::align_val_tal); (30)(since C++20)Deallocates storage previously allocated by a matching
or
. These deallocation functions are called by
delete and delete[] expressions
and by
to deallocate memory after destructing (or failing to construct) objects with dynamic storage duration. They may also be called using regular function call syntax.
1-12)
deallocation functions. The standard library provides default implementations for these functions, for the effects of the default implementations, see
.
1-8) Called by delete and delete[] expressions. Invalidates any non-null ptr.
9-12) Called by placement new expressions upon
. operatordelete[] invalidates any non-null ptr.
If ptr is not a null pointer and one of the following conditions is satisfied, the behavior is undefined: For operatordelete, the value of ptr does not represent the address of a block of memory allocated by an earlier call to (possibly replaced) operatornew(std::size_t) (for overloads (1,5,9)) or operatornew(std::size_t,std::align_val_t) (for overloads (3,7,11)) which has not been invalidated by an intervening call to operatordelete.
For operatordelete[], the value of ptr does not represent the address of a block of memory allocated by an earlier call to (possibly replaced) operatornew[](std::size_t) (for overloads (2,6,10)) or operatornew[](std::size_t,std::align_val_t) (for overloads (4,8,12)) which has not been invalidated by an intervening call to operatordelete[].
13,14) Called by placement new expressions that invoked
non-allocating placement allocation function
when any part of the initialization in the expression terminates by throwing an exception. Performs no action.
15-30) User-defined deallocation functions called by delete, delete[] and placement new expressions.
27-30) If defined, delete expressions does not execute the destructor for *ptr before placing a call to operatordelete. Instead, direct invocation of the destructor such as by ptr->~T(); becomes the responsibility of this operatordelete.
Overloads (
) are implicitly declared in each translation unit even if the
header is not included.
See
for the criteria of selecting overload.
Parameters
ptr - pointer to a memory block to deallocate or a null pointer sz - the size that was passed to the matching allocation function place - pointer used as the placement parameter in the matching placement new tag - overload disambiguation tag matching the tag used by non-throwing operator new al - alignment of the object or array element that was allocated args - arbitrary parameters matching a placement allocation function (may include
and
) Exceptions
All deallocation functions are noexcept(true) unless specified otherwise in the declaration.
(since C++11)If a deallocation function terminates by throwing an exception, the behavior is undefined, even if it is declared with noexcept(false)(since C++11).
Global replacements
Overloads (
) are
. The effects of the default versions are:
1) If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the earlier call to operatornew.
2) Calls operatordelete(ptr) as if overload (1) can reclaim the storage allocated by the earlier call to operatornew[].
3) Same as (1).
4) Calls operatordelete(ptr,al) as if overload (3) can reclaim the storage allocated by the earlier call to operatornew[].
5) Calls operatordelete(ptr).
6) Calls operatordelete[](ptr).
7) Calls operatordelete(ptr,al).
8) Calls operatordelete[](ptr,al).
9) Calls operatordelete(ptr).
10) Calls operatordelete[](ptr).
11) Calls operatordelete(ptr,al).
12) Calls operatordelete[](ptr,al).
Global operators new/delete replacement:
Run this code
#include<cstdio>#include<cstdlib>#include<new>// no inline, required by [replacement.functions]/3void*operatornew(std::size_tsz){std::printf("1) new(size_t), size = %zu\n",sz);if(sz==0)++sz;// avoid std::malloc(0) which may return nullptr on successif(void*ptr=std::malloc(sz))returnptr;throwstd::bad_alloc{};// required by [new.delete.single]/3}// no inline, required by [replacement.functions]/3void*operatornew[](std::size_tsz){std::printf("2) new[](size_t), size = %zu\n",sz);if(sz==0)++sz;// avoid std::malloc(0) which may return nullptr on successif(void*ptr=std::malloc(sz))returnptr;throwstd::bad_alloc{};// required by [new.delete.single]/3}voidoperatordelete(void*ptr)noexcept{std::puts("3) delete(void*)");std::free(ptr);}voidoperatordelete(void*ptr,std::size_tsize)noexcept{std::printf("4) delete(void*, size_t), size = %zu\n",size);std::free(ptr);}voidoperatordelete[](void*ptr)noexcept{std::puts("5) delete[](void* ptr)");std::free(ptr);}voidoperatordelete[](void*ptr,std::size_tsize)noexcept{std::printf("6) delete[](void*, size_t), size = %zu\n",size);std::free(ptr);}intmain(){int*p1=newint;deletep1;int*p2=newint[10];// guaranteed to call the replacement in C++11delete[]p2;}Possible output:
// Compiled with GCC-5 in C++17 mode to obtain the following: 1) op new(size_t), size = 4 4) op delete(void*, size_t), size = 4 2) op new[](size_t), size = 40 5) op delete[](void* ptr) Overloads of operatordelete and operatordelete[] with additional user-defined parameters ("placement forms", (
)) may be declared at global scope as usual, and are called by the matching placement forms of new expressions if a constructor of the object that is being allocated throws an exception.
The standard library placement forms of operatordelete and operatordelete[](
) cannot be replaced and can only be customized if the placement new expression did not use the ::new syntax, by providing a class-specific placement delete (
) with matching signature: voidT::operatordelete(void*,void*) or voidT::operatordelete[](void*,void*).
Class-specific overloads
Deallocation functions (
) may be defined as static member functions of a class. These deallocation functions, if provided, are called by delete expressions when deleting objects (
) and arrays (
) of this class, unless the delete expression used the form ::delete which bypasses class-scope lookup. The keyword static is optional for these function declarations: whether the keyword is used or not, the deallocation function is always a static member function.
The delete expression looks for appropriate deallocation function's name starting from the class scope (array form looks in the scope of the array element class) and proceeds to the global scope if no members are found as usual. Note, that as per
, any deallocation functions declared in class scope hides all global deallocation functions.
If the static type of the object that is being deleted differs from its dynamic type (such as when deleting a
object through a pointer to base), and if the destructor in the static type is virtual, the single object form of delete begins lookup of the deallocation function's name starting from the point of definition of the final overrider of its virtual destructor. Regardless of which deallocation function would be executed at run time, the statically visible version of operatordelete must be accessible in order to compile. In other cases, when deleting an array through a pointer to base, or when deleting through pointer to base with non-virtual destructor, the behavior is undefined.
If the single-argument overload (
) is not provided, but the size-aware overload taking
as the second parameter (
) is provided, the size-aware form is called for normal deallocation, and the C++ runtime passes the size of the object to be deallocated as the second argument. If both forms are defined, the size-unaware version is called.
Run this code
#include<cstddef>#include<iostream>// sized class-specific deallocation functionsstructX{staticvoidoperatordelete(void*ptr,std::size_tsz){std::cout<<"custom delete for size "<<sz<<'\n';::operatordelete(ptr);}staticvoidoperatordelete[](void*ptr,std::size_tsz){std::cout<<"custom delete for size "<<sz<<'\n';::operatordelete[](ptr);}};intmain(){X*p1=newX;deletep1;X*p2=newX[10];delete[]p2;}Possible output:
custom delete for size 1 custom delete for size 18Overloads of operator delete and operator delete[] with additional user-defined parameters ("placement forms", (
)) may also be defined as class members. When the failed placement new expression looks for the corresponding placement delete function to call, it begins lookup at class scope before examining the global scope, and looks for the function with the signature matching the placement new:
Run this code
#include <cstddef> #include <iostream> #include <stdexcept> struct X { X() { throw std::runtime_error("X(): std::runtime_error"); } // custom placement new static void* operator new(std::size_t sz, bool b) { std::cout << "custom placement new called, b = " << b << '\n'; return ::operator new(sz); } // custom placement delete static void operator delete(void* ptr, bool b) { std::cout << "custom placement delete called, b = " << b << '\n'; ::operator delete(ptr); } }; int main() { try { [[maybe_unused]] X* p1 = new (true) X; } catch (const std::exception& ex) { std::cout << ex.what() << '\n'; } }Output:
custom placement new called, b = 1 custom placement delete called, b = 1 X(): std::runtime_errorIf class-level operator delete is a template function, it must have the return type of void, the first argument void*, and it must have two or more parameters. In other words, only placement forms can be templates. A template instance is never a usual deallocation function, regardless of its signature. The specialization of the template operator delete is chosen with
.
Notes
The call to the class-specific T::operator delete on a polymorphic class is the only case where a static member function is called through dynamic dispatch.
macro ValueStdFeature
(C++14)Sized deallocation
(C++20)Destroying operator delete (compiler support)
(C++20)Destroying operator delete (library support) Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++98 user-defined deallocation functions were permitted to throw throwing from a deallocation function
results in undefined behavior
C++98 any use of an invalid pointer value was undefined behavior only indirection and deallocation are
C++98 replacing (
) did not affect the default behavior of (
)the default behavior
changes accordingly
C++98 replacing (
) did not affect the default behavior of (
)the default behavior
changes accordingly
C++98 replacements of the replaceable deallocation
functions could be declared inlineprohibited, no diagnostic required
C++14 overloads taking (void*, std::size_t, const
std::nothrow_t&) were specified, but could never be called removed spurious overloads See also