Namespaces
Variants

operator new , operator new[]

From cppreference.net
< cpp ‎ | memory ‎ | new
Utilities library
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (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)
(C++11) (until C++23)
Definido en el encabezado <new>
Funciones de asignación reemplazables
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) (desde C++17)
void * operator new [ ] ( std:: size_t count, std:: align_val_t al ) ;
(4) (desde C++17)
Funciones de asignación reemplazables que no lanzan excepciones
void * operator new ( std:: size_t count, const std:: nothrow_t & tag ) ;
(5) (noexcept desde C++11)
void * operator new [ ] ( std:: size_t count, const std:: nothrow_t & tag ) ;
(6) (noexcept desde C++11)
void * operator new ( std:: size_t count, std:: align_val_t al,
const std:: nothrow_t & tag ) noexcept ;
(7) (desde C++17)
void * operator new [ ] ( std:: size_t count, std:: align_val_t al,
const std:: nothrow_t & tag ) noexcept ;
(8) (desde C++17)
Funciones de asignación de colocación sin asignación de memoria
void * operator new ( std:: size_t count, void * ptr ) ;
(9) (noexcept desde C++11)
(constexpr desde C++26)
void * operator new [ ] ( std:: size_t count, void * ptr ) ;
(10) (noexcept desde C++11)
(constexpr desde C++26)
Funciones de asignación de ubicación definidas por el usuario
void * operator new ( std:: size_t count, /* args... */ ) ;
(11)
void * operator new [ ] ( std:: size_t count, /* argumentos... */ ) ;
(12)
void * operator new ( std:: size_t count,
std:: align_val_t al, /* args... */ ) ;
(13) (desde C++17)
void * operator new [ ] ( std:: size_t count,
std:: align_val_t al, /* args... */ ) ;
(14) (desde C++17)
Funciones de asignación específicas de clase
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) (desde C++17)
void * T :: operator new [ ] ( std:: size_t count, std:: align_val_t al ) ;
(18) (desde C++17)
Funciones de asignación de ubicación específicas de clase
void * T :: operator new ( std:: size_t count, /* args... */ ) ;
(19)
void * T :: operator new [ ] ( std:: size_t count, /* args... */ ) ;
(20)
void * T :: operator new ( std:: size_t count,
std:: align_val_t al, /* args... */ ) ;
(21) (desde C++17)
void * T :: operator new [ ] ( std:: size_t count,
std:: align_val_t al, /* argumentos... */ ) ;
(22) (desde C++17)

Intenta asignar el número solicitado de bytes, y la solicitud de asignación puede fallar (incluso si el número solicitado de bytes es cero). Estas funciones de asignación son llamadas por new expressions para asignar memoria en la cual el nuevo objeto sería entonces inicializado. También pueden ser llamadas usando la sintaxis regular de llamada a función.

1-8) Funciones de asignación reemplazables . La biblioteca estándar proporciona implementaciones predeterminadas para estas funciones, para los efectos de las implementaciones predeterminadas, consulte abajo .
9,10) Llamado por las expresiones de placement new estándar . No realiza ninguna acción y retorna ptr sin modificar.
Si esta función es llamada mediante placement new y ptr es un puntero nulo, el comportamiento es indefinido.
11-22) Funciones de asignación definidas por el usuario llamadas por new expressions.

Sobrecargas ( 1-4 ) se declaran implícitamente en cada unidad de traducción incluso si el <new> header no está incluido.

Consulte new expression para los criterios de selección de sobrecarga.

Contenidos

Parámetros

count - número de bytes a asignar
ptr - puntero a un área de memoria para inicializar el objeto
tag - etiqueta de desambiguación utilizada para seleccionar sobrecargas no lanzadoras
al - alineación a utilizar, un valor inválido conduce a comportamiento indefinido

Valor de retorno

1-4) Si la asignación tiene éxito, un puntero no nulo p0 que apunta a memoria adecuadamente alineada de tamaño al menos size y es diferente de cualquier valor previamente devuelto p1 , a menos que ese valor p1 haya sido posteriormente pasado a una función de desasignación reemplazable ; si la asignación falla, no retorna (se lanza una excepción, ver más abajo).
5-8) Igual que ( 1-4 ) , pero devuelve un puntero nulo si la asignación falla.
9,10) ptr
11-22) Igual que ( 1-4 ) si la función no retorna en caso de fallo de asignación, de lo contrario igual que ( 5-8 ) .

Excepciones

1-4) Lanza una excepción de un tipo que coincidiría con un manejador de tipo std::bad_alloc en caso de fallo al asignar memoria.
11-22) Igual que ( 1-4 ) si la función no retorna en caso de fallo de asignación, de lo contrario igual que ( 5-8 ) .

Reemplazos globales

Sobrecargas ( 1-8 ) son reemplazables . Los efectos de las versiones por defecto son:

1) Intenta asignar el almacenamiento solicitado. Si el intento implica una llamada a std::malloc o a std::aligned_alloc no está especificado.
  • Si el intento es exitoso, devuelve un puntero al almacenamiento asignado.
  • En caso contrario, si actualmente no hay un new-handler instalado, lanza std::bad_alloc .
  • En caso contrario, llama al new-handler actualmente instalado.
    • Si el new-handler retorna, inicia otro intento de asignación.
    • En caso contrario, finaliza la invocación actual.
2) Devuelve operator new ( count ) .
3) Igual que (1) .
4) Devuelve operator new ( count, al ) .
5-8) Llama (1-4) respectivamente con los mismos argumentos excepto por tag .
  • Si la llamada retorna normalmente, devuelve el resultado de esa llamada.
  • En caso contrario, devuelve un puntero nulo.

En implementaciones independientes , está definido por la implementación si las versiones predeterminadas de ( 1-8 ) satisfacen los comportamientos requeridos anteriormente. Se recomienda que las implementaciones independientes, si alguna de estas versiones predeterminadas cumple con los requisitos de una implementación hospedada, todas deberían hacerlo.

(since C++26)

Reemplazo de operadores operator s new / delete globales:

#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;
}

Salida posible:

// 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)

Las sobrecargas de operator new y operator new[] con parámetros adicionales definidos por el usuario ("formas de colocación", versiones ( 11-14 ) ) pueden declararse en el ámbito global como es usual, y son llamadas por las correspondientes formas de colocación de las expresiones new .

Las formas de ubicación sin asignación de la biblioteca estándar de operator new ( 9,10 ) no pueden ser reemplazadas y solo pueden personalizarse si la expresión de ubicación new no utilizó la sintaxis :: new , proporcionando una ubicación específica de clase new ( 19,20 ) con firma coincidente: void * T :: operator new ( std:: size_t , void * ) o void * T :: operator new [ ] ( std:: size_t , void * ) .

La forma de colocación void * operator new ( std:: size_t , std:: size_t ) no está permitida porque la firma coincidente de la función de desasignación, void operator delete ( void * , std:: size_t ) , es una función de desasignación normal (no de colocación).

(desde C++14)

Sobrecargas específicas de la clase

Tanto las funciones de asignación de objetos individuales como de arreglos pueden definirse como funciones miembro estáticas públicas de una clase (versiones ( 15-18 ) ). Si se definen, estas funciones de asignación son llamadas por las expresiones new para asignar memoria para objetos individuales y arreglos de esta clase, a menos que la expresión new utilice la forma :: new que omite la búsqueda en el ámbito de la clase. La palabra clave static es opcional para estas funciones: tanto si se utiliza como si no, la función de asignación es una función miembro estática.

La expresión new busca primero el nombre de la función de asignación apropiada en el ámbito de la clase, y después en el ámbito global. Nótese que, de acuerdo con las reglas de búsqueda de nombres , cualquier función de asignación declarada en el ámbito de la clase oculta todas las funciones de asignación globales para las expresiones new que intentan asignar objetos de esta clase.

Al asignar objetos y arreglos de objetos cuya alineación excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga se realiza dos veces: primero, para las firmas de función conscientes de la alineación, luego para las firmas de función no conscientes de la alineación. Esto significa que si una clase con alineación extendida tiene una función de asignación específica de clase no consciente de la alineación, será esa función la que se llamará, no la función de asignación global consciente de la alineación. Esto es intencional: se espera que el miembro de clase sepa mejor cómo manejar esa clase.

(desde C++17)

Al asignar objetos y arreglos de objetos cuya alineación no excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga se realiza dos veces: primero, para las firmas de función que no consideran la alineación, luego para las firmas de función que sí consideran la alineación.

(since C++20)
#include <cstddef>
#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;
}

Salida posible:

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

Las sobrecargas de operator new y operator new[] con parámetros adicionales definidos por el usuario ("formas de colocación"), también pueden definirse como miembros de clase ( 19-22 ) ). Cuando la expresión de colocación new con la firma correspondiente busca la función de asignación correspondiente para llamar, comienza en el ámbito de la clase antes de examinar el ámbito global, y si se proporciona el new de colocación específico de la clase, se llama.

Al asignar objetos y arreglos de objetos cuya alineación excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga para las formas de colocación se realiza dos veces al igual que para las formas regulares: primero, para las firmas de funciones conscientes de la alineación, luego para las firmas de funciones no conscientes de la alineación.

(desde C++17)

Al asignar objetos y arreglos de objetos cuya alineación no excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga para las formas de colocación se realiza dos veces al igual que para las formas regulares: primero, para las firmas de función que no tienen en cuenta la alineación, luego para las firmas de función que sí tienen en cuenta la alineación.

(desde C++20)
#include <cstddef>
#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&)
    {}
}

Salida:

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

Si el operador a nivel de clase operator new es una función plantilla, debe tener el tipo de retorno void * , el primer argumento std::size_t , y debe tener dos o más parámetros. En otras palabras, solo las formas de colocación pueden ser plantillas.

Notas

Aunque el placement no asignador new ( 9,10 ) no puede ser reemplazado, una función con la misma firma puede definirse en el ámbito de la clase como se describió anteriormente. Además, se permiten sobrecargas globales que parecen placement new pero toman un tipo de puntero no void como segundo argumento, por lo que el código que quiere asegurar que se llame al verdadero placement new (ej. std::allocator::construct ), debe usar :: new y también convertir el puntero a void * .

Si el comportamiento de una función de desasignación no satisface las restricciones predeterminadas, el comportamiento es indefinido.

Las siguientes funciones deben ser seguras para hilos (thread-safe):

Las llamadas a estas funciones que asignan o desasignan una unidad particular de almacenamiento ocurren en un único orden total, y cada llamada de desasignación happens-before la siguiente asignación (si existe) en este orden.

(desde C++11)

No está especificado si las versiones de biblioteca de operator new realizan llamadas a std::malloc o std::aligned_alloc (desde C++17) .

Para cargar un archivo grande, el mapeo de archivos mediante funciones específicas del sistema operativo, por ejemplo, mmap en POSIX o CreateFileMapping ( A / W ) junto con MapViewOfFile en Windows, es preferible a asignar un búfer para la lectura de archivos.

Macro de prueba de características Valor Std Característica
__cpp_lib_freestanding_operator_new 202306L (C++26) soporte freestanding para operator new reemplazable [1]
0 (C++26) sin soporte freestanding
__cpp_lib_constexpr_new 202406L (C++26) constexpr placement new y new [ ]
  1. Formalmente, esta macro se expande a 202306L si todas las versiones por defecto de las funciones de asignación global reemplazables cumplen con los requisitos de una implementación hospedada.

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 521 C++98 cualquier clase derivada de std::bad_alloc podría ser lanzada,
incluso si la base std::bad_alloc es ambigua o inaccesible
la excepción lanzada debe coincidir
con un manejador de tipo std::bad_alloc
LWG 9 C++98 múltiples llamadas para asignar cero
bytes podrían devolver el mismo puntero
solo permitido si todos los punteros
previamente devueltos han sido
pasados a funciones de desasignación
LWG 206 C++98 reemplazar las funciones de asignación reemplazables no
afectaba los comportamientos por defecto de las correspondientes
funciones de asignación reemplazables que no lanzan excepciones
los comportamientos por defecto
cambian en consecuencia
LWG 404 C++98 los reemplazos de las funciones de asignación
reemplazables podían declararse inline
prohibido, no se requiere diagnóstico

Referencias

  • Estándar C++23 (ISO/IEC 14882:2024):
  • 17.7 Gestión de memoria dinámica [support.dynamic]
  • Estándar C++20 (ISO/IEC 14882:2020):
  • 17.6 Gestión de memoria dinámica [support.dynamic]
  • Estándar C++17 (ISO/IEC 14882:2017):
  • 21.6 Gestión de memoria dinámica [support.dynamic]
  • Estándar C++14 (ISO/IEC 14882:2014):
  • 18.6 Gestión de memoria dinámica [support.dynamic]
  • Estándar C++11 (ISO/IEC 14882:2011):
  • 18.6 Gestión de memoria dinámica [support.dynamic]
  • Estándar C++03 (ISO/IEC 14882:2003):
  • 18.4 Gestión de memoria dinámica [lib.support.dynamic]
  • Estándar C++98 (ISO/IEC 14882:1998):
  • 18.4 Gestión de memoria dinámica [lib.support.dynamic]

Véase también

[static] (C++23)
asigna memoria usando Allocator
(función miembro estática pública de std::generator<Ref,V,Allocator>::promise_type )
funciones de desasignación
(función)
obtiene el manejador de memoria actual
(función)
registra un nuevo manejador
(función)
(obsoleto en C++17) (eliminado en C++20)
obtiene almacenamiento no inicializado
(plantilla de función)
asigna memoria
(función)
asigna memoria alineada
(función)