operator delete, operator delete[]
Defined in header
<new>
|
||
replaceable deallocation functions
|
||
void operator delete ( void* ptr );
|
(1) | |
void operator delete[]( void* ptr );
|
(2) | |
void operator delete ( void* ptr, const std::nothrow_t& tag );
|
(3) | |
void operator delete[]( void* ptr, const std::nothrow_t& tag );
|
(4) | |
void operator delete ( void* ptr, std::size_t sz );
|
(5) | (since C++14) |
void operator delete[]( void* ptr, std::size_t sz );
|
(6) | (since C++14) |
void operator delete ( void* ptr, std::size_t sz,
const std::nothrow_t& tag ); |
(7) | (since C++14) (until C++17) |
void operator delete[]( void* ptr, std::size_t sz,
const std::nothrow_t& tag ); |
(8) | (since C++14) (until C++17) |
placement deallocation functions
|
||
void operator delete ( void* ptr, void* place );
|
(9) | |
void operator delete[]( void* ptr, void* place );
|
(10) | |
void operator delete ( void* ptr, user-defined-args... );
|
(11) | |
void operator delete[]( void* ptr, user-defined-args... );
|
(12) | |
class-specific deallocation functions
|
||
void T::operator delete ( void* ptr );
|
(13) | |
void T::operator delete[]( void* ptr );
|
(14) | |
void T::operator delete ( void* ptr, std::size_t sz );
|
(15) | |
void T::operator delete[]( void* ptr, std::size_t sz );
|
(16) | |
void T::operator delete ( void* ptr, user-defined-args... );
|
(17) | |
void T::operator delete[]( void* ptr, user-defined-args... );
|
(18) | |
Deallocates storage previously allocated by a matching operator new. These deallocation functions are called by delete-expressions and by new-expressions to deallocate memory after destructing (or failing to construct) objects with dynamic storage duration. They may also be called using regular function call syntax.
ptr
is a null pointer or is a pointer previously obtained from the standard library implementation of operator new(size_t) or operator new(size_t, std::nothrow_t).ptr
is a null pointer or is a pointer previously obtained from the standard library implementation of operator new[](size_t) or operator new[](size_t, std::nothrow_t).In all cases, if ptr
is a null pointer, the standard library deallocation functions do nothing. If the pointer passed to the standard library deallocation function was not obtained from the corresponding standard library allocation function, the behavior is undefined.
After the standard library deallocation function returns, all pointers referring to any part of the deallocated storage become invalid.
Any use of a pointer that became invalid in this manner, even copying the pointer value into another variable, is undefined behavior. |
(until C++14) |
Indirection through a pointer that became invalid in this manner and passing it to a deallocation function (double-delete) is undefined behavior. Any other use is implementation-defined. |
(since C++14) |
Contents |
[edit] Parameters
ptr | - | pointer to a memory area 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 |
[edit] Return value
(none)
[edit] Exceptions
(none) | (until C++11) |
noexcept specification:
noexcept |
(since C++11) |
[edit] Global replacements
The versions (1-8) are implicitly declared in each translation unit even if the <new>
header is not included. These functions are replaceable: a user-provided non-member function with the same signature defined anywhere in the program, in any source file, replaces the corresponding implicit version for the entire program. Its declaration does not need to be visible.
The behavior is undefined if more than one replacement is provided in the program or if a replacement is defined with the inline
specifier, the program is ill-formed if a replacement is defined in namespace other than global namespace, or if it is defined as a static non-member function at global scope.
The single-object version (1) is called by the standard library implementations of all other versions (2-8), so replacing that one function is sufficient to handle all deallocations. | (since C++11) |
#include <cstdio> #include <cstdlib> // replacement of a minimal set of functions: void* operator new(std::size_t sz) { std::printf("global op new called, size = %zu\n",sz); return std::malloc(sz); } void operator delete(void* ptr) noexcept { std::puts("global op delete called"); std::free(ptr); } int main() { int* p1 = new int; delete p1; int* p2 = new int[10]; // guaranteed to call the replacement in C++11 delete[] p2; }
Possible output:
global op new called, size = 4 global op delete called global op new called, size = 40 global op delete called
Overloads of operator delete
and operator delete[]
with additional user-defined parameters ("placement forms", (11,12)) 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 operator delete (9,10) 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 (17,18) with matching signature: void T::operator delete(void*, void*)
or void T::operator delete[](void*, void*)
.
All deallocation functions are noexcept(true) unless specified otherwise in the declaration. |
(since C++11) |
[edit] Class-specific overloads
Deallocation functions (13-16) may be defined as static member functions of a class. These deallocation functions, if provided, are called by delete-expressions when deleting objects (versions (13) and (15)) and arrays (versions (14) and (17)) 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 first in the class scope (array form looks in the scope of the array element class), and after that in the global scope. Note, that as per name lookup rules, 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 polymorphic 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 operator delete 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 (13,14) is not provided, but the two-argument overload taking std::size_t
as the second parameter (15,16) is provided, the two-argument 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 single-argument version is called.
#include <iostream> // sized class-specific deallocation functions struct X { static void operator delete(void* ptr, std::size_t sz) { std::cout << "custom delete for size " << sz << '\n'; ::operator delete(ptr); } static void operator delete[](void* ptr, std::size_t sz) { std::cout << "custom delete for size " << sz << '\n'; ::operator delete(ptr); } }; int main() { X* p1 = new X; delete p1; X* p2 = new X[10]; delete[] p2; }
Possible output:
custom delete for size 1 custom delete for size 18
Overloads of operator delete
and operator delete[]
with additional user-defined parameters ("placement forms", (17,18)) may also be defined as class members. When the placement new expression with the matching signature looks for the corresponding placement delete function to call, it begins at class scope before examining the global scope, and if the class-specific placement delete is provided, it is called.
#include <stdexcept> #include <iostream> struct X { X() { throw 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 { X* p1 = new (true) X; } catch(const std::exception&) { } }
Output:
custom placement new called, b = 1 custom placement delete called, b = 1
If 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. The specialization of the template operator delete is chosen with template argument deduction.
[edit] 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.
[edit] See also
allocation functions (function) |
|
releases uninitialized storage (function) |
|
deallocates memory (function) |