# operator delete, operator delete[]

From cppreference.com
< cpp‎ | memory‎ | new

Defined in header `<new>` |  |
replaceable usual deallocation functions |  |
void operator delete ( void* ptr ); | (1) |
void operator delete[]( void* ptr ); | (2) |
void operator delete ( void* ptr, std::align_val_t al ); | (3) | (since C++17)
void operator delete[]( void* ptr, std::align_val_t al ); | (4) | (since C++17)
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, std::align_val_t al ); | (7) | (since C++17)
void operator delete[]( void* ptr, std::size_t sz, std::align_val_t al ); | (8) | (since C++17)
replaceable placement deallocation functions |  |
void operator delete ( void* ptr, const std::nothrow_t& tag ); | (9) |
void operator delete[]( void* ptr, const std::nothrow_t& tag ); | (10) |
void operator delete ( void* ptr, std::align_val_t al, const std::nothrow_t& tag ); | (11) | (since C++17)
void operator delete[]( void* ptr, std::align_val_t al, const std::nothrow_t& tag ); | (12) | (since C++17)
non-allocating placement deallocation functions |  |
void operator delete ( void* ptr, void* place ); | (13) |
void operator delete[]( void* ptr, void* place ); | (14) |
user-defined placement deallocation functions |  |
void operator delete ( void* ptr, args... ); | (15) |
void operator delete[]( void* ptr, args... ); | (16) |
class-specific usual deallocation functions |  |
void T::operator delete ( void* ptr ); | (17) |
void T::operator delete[]( void* ptr ); | (18) |
void T::operator delete ( void* ptr, std::align_val_t al ); | (19) | (since C++17)
void T::operator delete[]( void* ptr, std::align_val_t al ); | (20) | (since C++17)
void T::operator delete ( void* ptr, std::size_t sz ); | (21) |
void T::operator delete[]( void* ptr, std::size_t sz ); | (22) |
void T::operator delete ( void* ptr, std::size_t sz, std::align_val_t al ); | (23) | (since C++17)
void T::operator delete[]( void* ptr, std::size_t sz, std::align_val_t al ); | (24) | (since C++17)
class-specific placement deallocation functions |  |
void T::operator delete ( void* ptr, args... ); | (25) |
void T::operator delete[]( void* ptr, args... ); | (26) |
class-specific destroying deallocation functions |  |
void T::operator delete(T* ptr, std::destroying_delete_t); | (27) | (since C++20)
void T::operator delete(T* ptr, std::destroying_delete_t, std::align_val_t); | (28) | (since C++20)
void T::operator delete(T* ptr, std::destroying_delete_t, std::size_t); | (29) | (since C++20)
void T::operator delete(T* ptr, std::destroying_delete_t, std::size_t, std::align_val_t); | (30) | (since C++20)

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.

1) Called by delete-expressions to deallocate storage previously allocated for a single object. The behavior of the standard library implementation of this function is undefined unless `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).
2) Called by delete[]-expressions to deallocate storage previously allocated for an array of objects. The behavior of the standard library implementation of this function is undefined unless `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).
3,4) Same as (1,2), except called if the alignment requirement exceeds `__STDCPP_DEFAULT_NEW_ALIGNMENT__`
5-6) Called instead of (1-2) if a user-defined replacement is provided, except that it's unspecified whether (1-2) or (5-6) is called when deleting objects of incomplete type and arrays of non-class and trivially-destructible class types. A memory allocator can use the given size to be more efficient. The standard library implementations are identical to (1-2).
7-8) Same as (5-6), except called if the alignment requirement exceeds `__STDCPP_DEFAULT_NEW_ALIGNMENT__`
9) Called by the non-throwing single-object new-expressions if a constructor of the object throws an exception. The standard library implementation behaves the same as (1)
10) Called by the non-throwing array new[]-expressions if a constructor of any object throws an exception (after executing the destructors of all objects in the array that were successfully constructed). The standard library implementation behaves the same as (2)
11,12) Same as (9,10), except called if the alignment requirement exceeds `__STDCPP_DEFAULT_NEW_ALIGNMENT__`
13) Called by the standard single-object placement new expression if the object's constructor throws an exception. The standard library implementation of this function does nothing.
14) Called by the standard array form of the placement new expression if any of the objects' constructors throws an exception (after executing the destructors of all objects that were constructed successfully). The standard library implementation of this function does nothing.
15) If defined, called by the custom single-object placement new expression with the matching signature if the object's constructor throws an exception. If a class-specific version (25) is defined, it is called in preference to (9). If neither (25) nor (15) is provided by the user, no deallocation function is called.
16) If defined, called by the custom array form of placement new[] expression with the matching signature if any of the objects' constructors throws an exception (after executing the destructors for all objects that were constructed successfully). If a class-specific version (16) is defined, it is called in preference to (10). If neither (26) nor (16) is provided by the user, no deallocation function is called
17) If defined, called by the usual single-object delete-expressions if deallocating an object of type T.
18) If defined, called by the usual array delete[]-expressions if deallocating an array of objects of type T.
19,20) If defined, called in preference to (17,18) if the alignment requirement exceeds `__STDCPP_DEFAULT_NEW_ALIGNMENT__`.
21) If defined, and if (17) is not defined, called by the usual single-object delete-expressions if deallocating an object of type T.
22) If defined, and if (18) is not defined, called by the usual array delete[]-expressions if deallocating an array of objects of type T.
23,24) If defined, and if (19,20) are not defined, called in preference to allocator-unaware members if the alignment requirement exceeds `__STDCPP_DEFAULT_NEW_ALIGNMENT__`.
25) If defined, called by the custom single-object placement new expression with the matching signature if the object's constructor throws an exception. If this function is not provided, and a matching (15) is not provided either, no deallocation function is called.
26) If defined, called by the custom array form of placement new[] expression with the matching signature if any of the objects' constructors throws an exception (after executing the destructors for all objects that were constructed successfully). If this function is not provided, and a matching (16) is not provided either, no deallocation function is called.
27-30) If defined, delete-expressions does not execute the destructor for *p before placing a call to `operator delete`. Instead, direct invocation of the destructor such as by p->~T(); becomes the responsibility of this user-defined operator delete.

See delete-expression for exact details on the overload resolution rules between alignment-aware and alignment-unaware overloads of usual (non-placement) deallocation functions. | (since C++17)

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)

### 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 std::size_t and std::align_val_t)

### Return value

(none)

### Exceptions

(none) | (until C++11)
`noexcept` specification: noexcept | (since C++11)

### Global replacements

The replaceable deallocation functions (1-10) 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 standard library implementations of the nothrow versions (9,10) directly call the corresponding throwing versions (1,2). The standard library implementations of the size-aware deallocation functions (5-8) directly call the corresponding size-unaware deallocation functions (1-4). The standard library implementations of size-unaware throwing array forms (2,4) directly calls the corresponding single-object forms (1,3).

Thus, replacing the throwing single object deallocation functions (1,3) is sufficient to handle all deallocations.

(since C++11)

Run this code

    #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", (15,16)) 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 (13,14) 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 (25,26) 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)

### Class-specific overloads

Deallocation functions (17-24) may be defined as static member functions of a class. These deallocation functions, if provided, are called by delete-expressions when deleting objects (17,19,21) and arrays (18,20,22) 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 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 (17,18) is not provided, but the size-aware overload taking `std::size_t` as the second parameter (21,22) 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 <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", (25,26)) 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 <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.

### 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.

The following functions are required to be thread-safe:

- The library versions of `operator new` and `operator delete`
- User replacement versions of global `operator new` and `operator delete`
- std::calloc, std::malloc, std::realloc, std::aligned_alloc (since C++17), std::free

Calls to these functions that allocate or deallocate a particular unit of storage occur in a single total order, and each such deallocation call happens-before the next allocation (if any) in this order.

(since C++11)

### Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR | Applied to | Behavior as published | Correct behavior
--- | --- | --- | ---
LWG 2458 | C++14 | overloads taking (void*,size_t,const nothrow_t&) were specified, but could never be called | spurious overloads removed

### See also

operator new operator new[] | allocation functions (function)
return_temporary_buffer (deprecated in C++17)(removed in C++20) | frees uninitialized storage (function template)
free | deallocates memory (function)

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/memory/new/operator_delete&oldid=107682"