operator new, operator new[]

From cppreference.com
< cpp‎ | memory‎ | new
 
 
Utilities library
General utilities
Date and time
Function objects
Formatting library (C++20)
(C++11)
Relational operators (deprecated in C++20)
Integer comparison functions
(C++20)(C++20)(C++20)   
(C++20)
Swap and type operations
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Common vocabulary types
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Elementary string conversions
(C++17)
(C++17)
 
Dynamic memory management
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Allocators
Garbage collection support
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)



 
 
Defined in header <new>
replaceable allocation functions

[[nodiscard]]

(since C++20)
void* operator new  ( std::size_t count );
(1)
void* operator new[]( std::size_t count );
(2)
void* operator new  ( std::size_t count, std::align_val_t al );
(3) (since C++17)
void* operator new[]( std::size_t count, std::align_val_t al );
(4) (since C++17)
replaceable non-throwing allocation functions

noexcept

(since C++11)

[[nodiscard]]

(since C++20)
void* operator new  ( std::size_t count, const std::nothrow_t& tag );
(5)
void* operator new[]( std::size_t count, const std::nothrow_t& tag );
(6)
void* operator new  ( std::size_t count,
                      std::align_val_t al, const std::nothrow_t& );
(7) (since C++17)
void* operator new[]( std::size_t count,
                      std::align_val_t al, const std::nothrow_t& );
(8) (since C++17)
non-allocating placement allocation functions

noexcept

(since C++11)

[[nodiscard]]

(since C++20)
void* operator new  ( std::size_t count, void* ptr );
(9)
void* operator new[]( std::size_t count, void* ptr );
(10)
user-defined placement allocation functions
void* operator new  ( std::size_t count, user-defined-args... );
(11)
void* operator new[]( std::size_t count, user-defined-args... );
(12)
void* operator new  ( std::size_t count,
                      std::align_val_t al, user-defined-args... );
(13) (since C++17)
void* operator new[]( std::size_t count,
                      std::align_val_t al, user-defined-args... );
(14) (since C++17)
class-specific allocation functions
void* T::operator new  ( std::size_t count );
(15)
void* T::operator new[]( std::size_t count );
(16)
void* T::operator new  ( std::size_t count, std::align_val_t al );
(17) (since C++17)
void* T::operator new[]( std::size_t count, std::align_val_t al );
(18) (since C++17)
class-specific placement allocation functions
void* T::operator new  ( std::size_t count, user-defined-args... );
(19)
void* T::operator new[]( std::size_t count, user-defined-args... );
(20)
void* T::operator new  ( std::size_t count,
                         std::align_val_t al, user-defined-args... );
(21) (since C++17)
void* T::operator new[]( std::size_t count,
                         std::align_val_t al, user-defined-args... );
(22) (since C++17)

Attempts to allocate requested number of bytes, and the allocation request can fail (even if the requested number of bytes is zero). These allocation functions are called by new-expressions to allocate memory in which new object would then be initialized. They may also be called using regular function call syntax.

1) Called by non-array new-expressions to allocate storage required for a single object. The standard library implementation allocates count bytes from free store. In case of failure, the standard library implementation calls the function pointer returned by std::get_new_handler and repeats allocation attempts until new handler does not return or becomes a null pointer, at which time it throws std::bad_alloc. This function is required to return a pointer suitably aligned to point to an object of the requested size.
2) Called by the array form of new[]-expressions to allocate all storage required for an array (including possible new-expression overhead). The standard library implementation calls version (1).
3) Called by non-array new-expressions to allocate storage required for a single object whose alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__.
4) Called by the array form of new[]-expressions to allocate all storage required for an array of objects whose alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__.
5) Called by the non-throwing non-array new-expressions. The standard library implementation calls the version (1) and returns a null pointer on failure instead of propagating the exception.
6) Called by the non-throwing array form of new[]-expressions. The standard library implementation calls the version (2) and returns a null pointer on failure instead of propagating the exception.
7) Called by the non-throwing non-array new-expressions when the object's alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. The standard library implementation calls the version (3) and returns a null pointer on failure instead of propagating the exception.
8) Called by the non-throwing array form of new[]-expressions when the alignment requirement of array elements exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. The standard library implementation calls the version (4) and returns a null pointer on failure instead of propagating the exception.
9) Called by the standard single-object placement new expression. The standard library implementation performs no action and returns ptr unmodified. The behavior is undefined if this function is called through a placement new expression and ptr is a null pointer.
10) Called by the standard array form placement new expression. The standard library implementation performs no action and returns ptr unmodified. The behavior is undefined if this function is called through a placement new expression and ptr is a null pointer.
11) If defined, called by the custom single-object placement new expression with the matching signature. If a class-specific version (19) is defined, it is called in preference to (11). If neither (11) nor (19) is provided by the user, the placement new expression is ill-formed.
12) If defined, called by the custom array form placement new expression with the matching signature. If a class-specific version (20) is defined, it is called in preference to (12). If neither (12) nor (20) is provided by the user, the placement new expression is ill-formed.
13) If defined, called by the custom single-object placement new expression with the matching signature if the object's alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. If a class-specific version is defined ((15) or (17)), it is called instead. If neither class-specific nor global alignment-aware (this one) placement form is provided, alignment-unaware placement form (11) is looked up instead.
14) If defined, called by the custom array form placement new expression with the matching signature if the element's alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. If a class-specific version ((16) or (18)) is defined, it is called instead. If neither class-specific nor global alignment-aware (this one) placement form is provided, alignment-unaware placement form (12) is looked up instead.
15) If defined, called by the usual single-object new-expressions if allocating an object of type T.
16) If defined, called by the usual array new[]-expressions if allocating an array of objects of type T.
17) If defined, called by the usual single-object new-expressions if allocating an object of type T if its alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. If this overload is not provided, but alignment-unaware member form (15) is, alignment-unaware member overload is called instead.
18) If defined, called by the usual array new[]-expressions if allocating an array of objects of type T if its alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. If this overload is not provided, but alignment-unaware member form (16) is, alignment-unaware member overload is called instead.
19) If defined, called by the custom single-object placement new expression with the matching signature if allocating an object of type T.
20) If defined, called by the custom array form of placement new[] expression with the matching signature if allocating an array of objects of type T.
21) If defined, called by the custom single-object placement new expression with the matching signature if allocating an object of type T if its alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. If this overload is not provided, but alignment-unaware member form (19) is, alignment-unaware member overload is called instead.
22) If defined, called by the custom array form of placement new[] expression with the matching signature if allocating an array of objects of type T if its alignment requirement exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__. If this overload is not provided, but alignment-unaware member form (20) is, alignment-unaware member overload is called instead.

Parameters

count - number of bytes to allocate
ptr - pointer to a memory area to initialize the object at
tag - disambiguation tag used to select non-throwing overloads
al - alignment to use. The behavior is undefined if this is not a valid alignment value

Return value

1-4) If the allocation succeeds, a non-null pointer p0 which points to suitably aligned memory of size at least size and is different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function; if the allocation fails, does not return (an exception is thrown, see below).
5-8) Same as (1-4), but returns a null pointer if the allocation fails.
9-10) ptr.
11-22) Same as (1-4) if the function does not return on allocation failure, otherwise same as (5-8).

Exceptions

1-4) Throws an exception of a type that would match a handler of type std::bad_alloc on failure to allocate memory.
11-22) Same as (1-4) if the function does not return on allocation failure, otherwise same as (5-8).

Global replacements

The versions (1-4) are implicitly declared in each translation unit even if the <new> header is not included. Versions (1-8) are replaceable: a user-provided non-member function with the same signature defined anywhere in the program, in any source file, replaces the default version. Its declaration does not need to be visible.

The program is ill-formed, no diagnostic required if more than one replacement is provided in the program for any of the replaceable allocation function, or if a replacement is declared 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 (5-8) directly calls the corresponding throwing versions (1-4). The standard library implementation of the throwing array versions (2,4) directly calls the corresponding single-object version (1,3). Thus, replacing the throwing single object allocation functions is sufficient to handle all allocations.

Global operators new/delete replacement:

#include <cstdio>
#include <cstdlib>
#include <new>
 
// no inline, required by [replacement.functions]/3
void* operator new(std::size_t sz)
{
    std::printf("1) new(size_t), size = %zu\n", sz);
    if (sz == 0)
        ++sz; // avoid std::malloc(0) which may return nullptr on success
 
    if (void *ptr = std::malloc(sz))
        return ptr;
 
    throw std::bad_alloc{}; // required by [new.delete.single]/3
}
 
// no inline, required by [replacement.functions]/3
void* operator new[](std::size_t sz)
{
    std::printf("2) new[](size_t), size = %zu\n", sz);
    if (sz == 0)
        ++sz; // avoid std::malloc(0) which may return nullptr on success
 
    if (void *ptr = std::malloc(sz))
        return ptr;
 
    throw std::bad_alloc{}; // required by [new.delete.single]/3
}
 
void operator delete(void* ptr) noexcept
{
    std::puts("3) delete(void*)");
    std::free(ptr);
}
 
void operator delete(void* ptr, std::size_t size) noexcept
{
    std::printf("4) delete(void*, size_t), size = %zu\n", size);
    std::free(ptr);
}
 
void operator delete[](void* ptr) noexcept
{
    std::puts("5) delete[](void* ptr)");
    std::free(ptr);
}
 
void operator delete[](void* ptr, std::size_t size) noexcept
{
    std::printf("6) delete[](void*, size_t), size = %zu\n", size);
    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:

// 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 operator new and operator new[] with additional user-defined parameters ("placement forms", versions (11-14)) may be declared at global scope as usual, and are called by the matching placement forms of new-expressions.

The standard library's non-allocating placement forms of operator new (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 new (19,20) with matching signature: void* T::operator new(std::size_t, void*) or void* T::operator new[](std::size_t, void*).

The placement form void* operator new(std::size_t, std::size_t) is not allowed because the matching signature of the deallocation function, void operator delete(void*, std::size_t), is a usual (not placement) deallocation function.

(since C++14)

Class-specific overloads

Both single-object and array allocation functions may be defined as public static member functions of a class (versions (15-18)). If defined, these allocation functions are called by new-expressions to allocate memory for single objects and arrays of this class, unless the new expression used the form ::new which bypasses class-scope lookup. The keyword static is optional for these functions: whether used or not, the allocation function is a static member function.

The new expression looks for appropriate allocation function's name firstly in the class scope, and after that in the global scope. Note, that as per name lookup rules, any allocation functions declared in class scope hides all global allocation functions for the new-expressions that attempt to allocate objects of this class.

When allocating objects and arrays of objects whose alignment exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__, overload resolution is performed twice: first, for alignment-aware function signatures, then for alignment-unaware function signatures. This means that if a class with extended alignment has an alignment-unaware class-specific allocation function, it is the function that will be called, not the global alignment-aware allocation function. This is intentional: the class member is expected to know best how to handle that class.

(since C++17)

When allocating objects and arrays of objects whose alignment does not exceed __STDCPP_DEFAULT_NEW_ALIGNMENT__, overload resolution is performed twice: first, for alignment-unaware function signatures, then for alignment-aware function signatures.

(since C++20)
#include <iostream>
 
// class-specific allocation functions
struct X
{
    static void* operator new(std::size_t count)
    {
        std::cout << "custom new for size " << count << '\n';
        return ::operator new(count);
    }
 
    static void* operator new[](std::size_t count)
    {
        std::cout << "custom new[] for size " << count << '\n';
        return ::operator new[](count);
    }
};
 
int main()
{
    X* p1 = new X;
    delete p1;
    X* p2 = new X[10];
    delete[] p2;
}

Possible output:

custom new for size 1
custom new[] for size 10

Overloads of operator new and operator new[] with additional user-defined parameters ("placement forms"), may also be defined as class members (19-22)). When the placement new expression with the matching signature looks for the corresponding allocation function to call, it begins at class scope before examining the global scope, and if the class-specific placement new is provided, it is called.

When allocating objects and arrays of objects whose alignment exceeds __STDCPP_DEFAULT_NEW_ALIGNMENT__, overload resolution for placement forms is performed twice just as for regular forms: first, for alignment-aware function signatures, then for alignment-unaware function signatures.

(since C++17)

When allocating objects and arrays of objects whose alignment does not exceed __STDCPP_DEFAULT_NEW_ALIGNMENT__, overload resolution for placement forms is performed twice just as for regular forms: first, for alignment-unaware function signatures, then for alignment-aware function signatures.

(since C++20)
#include <iostream>
#include <stdexcept>
 
struct X
{
    X() { throw std::runtime_error(""); }
 
    // custom placement new
    static void* operator new(std::size_t count, bool b)
    {
        std::cout << "custom placement new called, b = " << b << '\n';
        return ::operator new(count);
    }
 
    // 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&)
    {}
}

Output:

custom placement new called, b = 1
custom placement delete called, b = 1

If class-level operator new is a template function, it must have the return type of void*, the first argument std::size_t, and it must have two or more parameters. In other words, only placement forms can be templates.

Notes

Even though the non-allocating placement new (9,10) cannot be replaced, a function with the same signature may be defined at class scope as described above. In addition, global overloads that look like placement new but take a non-void pointer type as the second argument are allowed, so the code that wants to ensure that the true placement new is called (e.g. std::allocator::construct), must use ::new and also cast the pointer to void*.

If the behavior of a deallocation function does not satisfy the default constraints, the behavior is undefined.

The following functions are required to be thread-safe:

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)

It is unspecified whether library versions of operator new make any calls to std::malloc or std::aligned_alloc (since C++17).

For loading a large file, file mapping via OS-specific functions, e.g. mmap on POSIX or CreateFileMapping(A/W) along with MapViewOfFile on Windows, is preferable to allocating a buffer for file reading.

Defect Reports

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

DR Applied to Behavior as published Correct behavior
CWG 521 C++98 any class derived from std::bad_alloc could be thrown,
even if the std::bad_alloc base is ambiguous or inaccessible
the exception thrown should match
a handler of type std::bad_alloc
LWG 9 C++98 multiple calls for allocating zero
bytes could yield the same pointer
only allowed if all such previously
yielded pointers have been
passed to deallocation functions
LWG 206 C++98 replacing the replaceable allocation functions did
not affect the default behaviors of the corresponding
replaceable non-throwing allocation functions
the default behaviors
change accordingly
LWG 404 C++98 replacements of the replaceable allocation
functions could be declared inline
prohibited, no diagnostic required

References

  • C++23 standard (ISO/IEC 14882:2023):
  • 17.7 Dynamic memory management [support.dynamic]
  • C++20 standard (ISO/IEC 14882:2020):
  • 17.6 Dynamic memory management [support.dynamic]
  • C++17 standard (ISO/IEC 14882:2017):
  • 21.6 Dynamic memory management [support.dynamic]
  • C++14 standard (ISO/IEC 14882:2014):
  • 18.6 Dynamic memory management [support.dynamic]
  • C++11 standard (ISO/IEC 14882:2011):
  • 18.6 Dynamic memory management [support.dynamic]

See also

deallocation functions
(function)
obtains the current new handler
(function)
registers a new handler
(function)
(deprecated in C++17)(removed in C++20)
obtains uninitialized storage
(function template)
allocates memory
(function)
allocates aligned memory
(function)