Namespaces
Variants

operator new, operator new[]

De es.cppreference.net
 
 
Biblioteca de utilidades
Soporte del lenguaje
Soporte de tipos (tipos básicos, RTTI)
Macros de prueba de características de la biblioteca (C++20)
Utilidades del programa
Funciones variádicas
Soporte de corrutinas (C++20)
Soporte de contratos (C++26)
Comparación de tres vías
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Utilidades generales
Operadores relacionales (obsoleto en C++20)
 
Biblioteca de gestión de memoria
Asignadores
Recursos de memoria
Almacenamiento no inicializado (hasta C++20*)
Soporte para recolector de basura (hasta 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 que no lanzan excepciones reemplazables
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 que no asignan
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 colocación definidas por el usuario
void* operator new  ( std::size_t count, /* args... */ );
(11)
void* operator new[]( std::size_t count, /* args... */ );
(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 colocació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, /* args... */ );
(22) (desde C++17)

Intenta asignar el número de bytes solicitado, y la solicitud de asignación puede fallar (incluso si el número de bytes solicitado es cero). Estas funciones de asignación son llamadas por las new expresiones new para asignar memoria en la que luego se inicializará el nuevo objeto. También pueden ser llamadas usando la sintaxis de llamada a función regular.

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 más abajo.
9,10) Llamadas por las expresiones new de colocaciónnew estándar. No realiza ninguna acción y devuelve ptrptr sin modificar.
Si esta función es llamada mediante newnew de colocación y ptrptr es un puntero nulo, el comportamiento no está definido.
11-22) Funciones de asignación definidas por el usuario llamadas por new expresiones new.

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

Consulte la new expresión new para los criterios de selección de sobrecarga.

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

Las sobrecargas (1-8) son reemplazables. Los efectos de las versiones predeterminadas son:

1) Intenta asignar el almacenamiento solicitado. Si el intento implica una llamada a std::malloc o std::aligned_alloc no está especificado.
  • Si el intento tiene éxito, devuelve un puntero al almacenamiento asignado, el almacenamiento está alineado a la alineación fundamental(hasta C++17)el almacenamiento está alineado a __STDCPP_DEFAULT_NEW_ALIGNMENT__(desde C++17).
  • De lo contrario, si actualmente no hay un new-handler instalado, lanza std::bad_alloc.
  • De lo contrario, llama al new-handler actualmente instalado.
    • Si el new-handler regresa, comienza otro intento de asignación.
    • De lo contrario, sale de la invocación actual.
2) Devuelve operator new(count).
3) Igual que (1), excepto que el almacenamiento devuelto está alineado a al.
4) Devuelve operator new(count, al).
5-8) Llama a (1-4) respectivamente con los mismos argumentos excepto tag.
  • Si la llamada regresa normalmente, devuelve el resultado de esa llamada.
  • De lo 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 en las implementaciones independientes, si alguna de estas versiones predeterminadas cumple con los requisitos de una implementación alojada, todas deberían hacerlo.

(desde C++26)

Reemplazo global de operators new/delete:

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

Posible salida:

// 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 de costumbre, y son llamadas por las formas de colocación coincidentes de las expresiones new.

Las formas de colocación no asignadoras de la biblioteca estándar de operator new (9,10) no pueden ser reemplazadas y solo pueden personalizarse si la expresión de colocación new no utilizó la sintaxis ::new, proporcionando una colocación new específica de clase (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 habitual (no de colocación).

(desde C++14)

Sobrecargas específicas de clase

Tanto las funciones de asignación de un solo objeto como las de asignación 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 expresiones new para asignar memoria para objetos individuales y arreglos de esta clase, a menos que la expresión new haya usado la forma ::new que omite la búsqueda en el ámbito de la clase. La palabra clave static es opcional para estas funciones: ya sea que se use o no, la función de asignación es una función miembro estática.

La expresión new busca el nombre de la función de asignación apropiada primero en el ámbito de la clase, y luego en el ámbito global. Nótese que, según 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 cuyo alineamiento excede __STDCPP_DEFAULT_NEW_ALIGNMENT__, la resolución de sobrecarga se realiza dos veces: primero, para las firmas de funciones conscientes del alineamiento, luego para las firmas de funciones inconscientes del alineamiento. Esto significa que si una clase con alineamiento extendido por new tiene una función de asignación específica de clase inconsciente del alineamiento, esa función será la llamada, no la función de asignación global consciente del alineamiento. Esto es intencional: se espera que el miembro de la clase sepa mejor cómo manejar esa clase.

(desde C++17)

Al asignar objetos y arreglos de objetos cuyo alineamiento no excede __STDCPP_DEFAULT_NEW_ALIGNMENT__, la resolución de sobrecarga se realiza dos veces: primero, para las firmas de funciones inconscientes del alineamiento, luego para las firmas de funciones conscientes del alineamiento.

(desde 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;
}

Posible salida:

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 ubicación"), también pueden definirse como miembros de clase (19-22)). Cuando la expresión de ubicación new con la firma coincidente 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 la ubicación específica de clase new se proporciona, es llamada.

Al asignar objetos y arreglos de objetos cuyo alineamiento excede __STDCPP_DEFAULT_NEW_ALIGNMENT__, la resolución de sobrecarga para las formas de ubicación se realiza dos veces, igual que para las formas regulares: primero, para las firmas de funciones conscientes del alineamiento, luego para las firmas de funciones inconscientes del alineamiento.

(desde C++17)

Al asignar objetos y arreglos de objetos cuyo alineamiento no excede __STDCPP_DEFAULT_NEW_ALIGNMENT__, la resolución de sobrecarga para las formas de ubicación se realiza dos veces, igual que para las formas regulares: primero, para las firmas de funciones inconscientes del alineamiento, luego para las firmas de funciones conscientes del alineamiento.

(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 operator new a nivel de clase es una función plantilla, debe tener el tipo de retorno de void*, el primer argumento std::size_t, y debe tener dos o más parámetros. En otras palabras, solo las formas de ubicació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)