Namespaces
Variants

operator delete , operator delete[]

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 desasignación usuales reemplazables
(1)
void operator delete ( void * ptr ) throw ( ) ;
(hasta C++11)
void operator delete ( void * ptr ) noexcept ;
(desde C++11)
(2)
void operator delete [ ] ( void * ptr ) throw ( ) ;
(hasta C++11)
void operator delete [ ] ( void * ptr ) noexcept ;
(desde C++11)
void operator delete ( void * ptr, std:: align_val_t al ) noexcept ;
(3) (desde C++17)
void operator delete [ ] ( void * ptr, std:: align_val_t al ) noexcept ;
(4) (desde C++17)
void operator delete ( void * ptr, std:: size_t sz ) noexcept ;
(5) (desde C++14)
void operator delete [ ] ( void * ptr, std:: size_t sz ) noexcept ;
(6) (desde C++14)
void operator delete ( void * ptr, std:: size_t sz,
std:: align_val_t al ) noexcept ;
(7) (desde C++17)
void operator delete [ ] ( void * ptr, std:: size_t sz,
std:: align_val_t al ) noexcept ;
(8) (desde C++17)
Funciones de desasignación de ubicación reemplazables
(9)
void operator delete ( void * ptr, const std:: nothrow_t & tag ) throw ( ) ;
(hasta C++11)
void operator delete ( void * ptr, const std:: nothrow_t & tag ) noexcept ;
(desde C++11)
(10)
void operator delete [ ] ( void * ptr, const std:: nothrow_t & tag ) throw ( ) ;
(hasta C++11)
void operator delete [ ] ( void * ptr, const std:: nothrow_t & tag ) noexcept ;
(desde C++11)
void operator delete ( void * ptr, std:: align_val_t al,
const std:: nothrow_t & tag ) noexcept ;
(11) (desde C++17)
void operator delete [ ] ( void * ptr, std:: align_val_t al,
const std:: nothrow_t & tag ) noexcept ;
(12) (desde C++17)
Funciones de desasignación de colocación sin asignación
(13)
void operator delete ( void * ptr, void * place ) throw ( ) ;
(hasta C++11)
void operator delete ( void * ptr, void * place ) noexcept ;
(desde C++11)
(14)
void operator delete [ ] ( void * ptr, void * place ) throw ( ) ;
(hasta C++11)
void operator delete [ ] ( void * ptr, void * place ) noexcept ;
(desde C++11)
Funciones de desasignación de ubicación definidas por el usuario
void operator delete ( void * ptr, args... ) ;
(15)
void operator delete [ ] ( void * ptr, args... ) ;
(16)
Funciones de desasignación usuales específicas de la clase
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) (desde C++17)
void T :: operator delete [ ] ( void * ptr, std:: align_val_t al ) ;
(20) (desde 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) (desde C++17)
void T :: operator delete [ ] ( void * ptr, std:: size_t sz, std:: align_val_t al ) ;
(24) (desde C++17)
Funciones de desasignación de colocación específicas de clase
void T :: operator delete ( void * ptr, args... ) ;
(25)
void T :: operator delete [ ] ( void * ptr, args... ) ;
(26)
Funciones de desasignación destructoras usuales específicas de clase
void T :: operator delete ( T * ptr, std:: destroying_delete_t ) ;
(27) (desde C++20)
void T :: operator delete ( T * ptr, std:: destroying_delete_t ,
std:: align_val_t al ) ;
(28) (desde C++20)
void T :: operator delete ( T * ptr, std:: destroying_delete_t , std:: size_t sz ) ;
(29) (desde C++20)
void T :: operator delete ( T * ptr, std:: destroying_delete_t ,
std:: size_t sz, std:: align_val_t al ) ;
(30) (desde C++20)

Desasigna el almacenamiento previamente asignado por un operator new o operator new[] correspondiente. Estas funciones de desasignación son llamadas por las delete y delete [ ] expressions y por las placement new expressions para desasignar memoria después de destruir (o fallar al construir) objetos con duración de almacenamiento dinámico. También pueden ser llamadas usando la sintaxis regular de llamada a función.

1-12) Funciones de desasignación reemplazables . La biblioteca estándar proporciona implementaciones predeterminadas para estas funciones, para los efectos de las implementaciones predeterminadas, consulte abajo .
1-8) Llamado por las expresiones delete y delete [ ] . Invalida cualquier ptr no nulo.
9-12) Llamado por expresiones de colocación new cuando ocurre fallo de inicialización . operator delete [ ] invalida cualquier ptr no nulo.
Si ptr no es un puntero nulo y se satisface una de las siguientes condiciones, el comportamiento es indefinido:
  • Para operator delete , el valor de ptr no representa la dirección de un bloque de memoria asignado por una llamada anterior a (posiblemente reemplazado) operator new ( std:: size_t ) (para las sobrecargas (1,5,9) ) o operator new ( std:: size_t , std:: align_val_t ) (para las sobrecargas (3,7,11) ) que no ha sido invalidado por una llamada intermedia a operator delete .
  • Para operator delete [ ] , el valor de ptr no representa la dirección de un bloque de memoria asignado por una llamada anterior a (posiblemente reemplazado) operator new [ ] ( std:: size_t ) (para las sobrecargas (2,6,10) ) o operator new [ ] ( std:: size_t , std:: align_val_t ) (para las sobrecargas (4,8,12) ) que no ha sido invalidado por una llamada intermedia a operator delete [ ] .
13,14) Llamado por expresiones de colocación new que invocaron la función de asignación de colocación no asignadora cuando cualquier parte de la inicialización en la expresión termina lanzando una excepción. No realiza ninguna acción.
15-30) Funciones de desasignación definidas por el usuario llamadas por delete , delete [ ] y expresiones de colocación new .
27-30) Si está definido, delete expressions no ejecuta el destructor para * ptr antes de realizar una llamada a operator delete . En su lugar, la invocación directa del destructor como mediante ptr - > ~T ( ) ; se convierte en responsabilidad de este operator delete .

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

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

Contenidos

Parámetros

ptr - puntero a un bloque de memoria para desasignar o un puntero nulo
sz - el tamaño que se pasó a la función de asignación correspondiente
place - puntero utilizado como parámetro de colocación en el placement new correspondiente
tag - etiqueta de desambiguación de sobrecarga que coincide con la etiqueta utilizada por el operator new no lanzador
al - alineación del objeto o elemento de matriz que fue asignado
args - parámetros arbitrarios que coinciden con una función de asignación de colocación (puede incluir std::size_t y std::align_val_t )

Excepciones

Todas las funciones de desasignación son noexcept ( true ) a menos que se especifique lo contrario en la declaración.

(desde C++11)

Si una función de desasignación termina lanzando una excepción, el comportamiento es indefinido , incluso si está declarada con noexcept ( false ) (desde C++11) .

Reemplazos globales

Sobrecargas ( 1-12 ) son reemplazables . Los efectos de las versiones predeterminadas son:

1) Si ptr es nulo, no hace nada. De lo contrario, reclama el almacenamiento asignado por la llamada anterior a operator new .
2) Llama a operator delete ( ptr ) como si la sobrecarga (1) pudiera recuperar el almacenamiento asignado por la llamada anterior a operator new [ ] .
3) Igual que (1) .
4) Llama a operator delete ( ptr, al ) como si la sobrecarga (3) pudiera recuperar el almacenamiento asignado por la llamada anterior a operator new [ ] .
5) Llama operator delete ( ptr ) .
6) Llama a operator delete [ ] ( ptr ) .
7) Llama operator delete ( ptr, al ) .
8) Llama a operator delete [ ] ( ptr, al ) .
9) Llama operator delete ( ptr ) .
10) Llama a operator delete [ ] ( ptr ) .
11) Llama a operator delete ( ptr, al ) .
12) Llama operator delete [ ] ( ptr, al ) .

Operadores operator globales new / delete de reemplazo:

#include <cstdio>
#include <cstdlib>
#include <new>
// no inline, requerido por [replacement.functions]/3
void* operator new(std::size_t sz)
{
    std::printf("1) new(size_t), size = %zu\n", sz);
    if (sz == 0)
        ++sz; // evitar std::malloc(0) que puede retornar nullptr en éxito
    if (void *ptr = std::malloc(sz))
        return ptr;
    throw std::bad_alloc{}; // requerido por [new.delete.single]/3
}
// no inline, requerido por [replacement.functions]/3
void* operator new[](std::size_t sz)
{
    std::printf("2) new[](size_t), size = %zu\n", sz);
    if (sz == 0)
        ++sz; // evitar std::malloc(0) que puede retornar nullptr en éxito
    if (void *ptr = std::malloc(sz))
        return ptr;
    throw std::bad_alloc{}; // requerido por [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]; // garantizado llamar al reemplazo en C++11
    delete[] p2;
}

Salida posible:

// Compilado con GCC-5 en modo C++17 para obtener lo siguiente:
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)

Sobrecargas de operator delete y operator delete [ ] con parámetros adicionales definidos por el usuario ("formas de colocación", ( 15,16 ) ) pueden declararse en el ámbito global como es usual, y son llamadas por las formas de colocación correspondientes de las expresiones new si un constructor del objeto que está siendo asignado lanza una excepción.

Las formas de colocación de la biblioteca estándar de operator delete y operator delete [ ] ( 13,14 ) no pueden ser reemplazadas y solo pueden personalizarse si la expresión de colocación new no utilizó la sintaxis :: new , proporcionando un delete de colocación específico de clase ( 25,26 ) con firma coincidente: void T :: operator delete ( void * , void * ) o void T :: operator delete [ ] ( void * , void * ) .

Sobrecargas específicas de la clase

Funciones de desasignación ( 17-24 ) pueden definirse como funciones miembro estáticas de una clase. Estas funciones de desasignación, si se proporcionan, son llamadas por expresiones delete al eliminar objetos ( 17,19,21 ) y arrays ( 18,20,22 ) de esta clase, a menos que la expresión delete utilice la forma :: delete que omite la búsqueda en el ámbito de la clase. La palabra clave static es opcional para estas declaraciones de función: independientemente de si se utiliza la palabra clave o no, la función de desasignación siempre es una función miembro estática.

La expresión delete busca el nombre de la función de desasignación apropiada comenzando desde el ámbito de la clase (la forma de array busca en el ámbito de la clase del elemento del array) y procede al ámbito global si no se encuentran miembros como es habitual. Nótese que, de acuerdo con las reglas de búsqueda de nombres , cualquier función de desasignación declarada en el ámbito de la clase oculta todas las funciones de desasignación globales.

Si el tipo estático del objeto que se está eliminando difiere de su tipo dinámico (como cuando se elimina un objeto polimórfico a través de un puntero a la clase base), y si el destructor en el tipo estático es virtual, la forma de delete para objeto único comienza la búsqueda del nombre de la función de desasignación desde el punto de definición del final overrider de su destructor virtual. Independientemente de qué función de desasignación se ejecutaría en tiempo de ejecución, la versión estáticamente visible de operator delete debe ser accesible para poder compilar. En otros casos, cuando se elimina un array a través de un puntero a base, o cuando se elimina a través de un puntero a base con destructor no virtual, el comportamiento es indefinido.

Si la sobrecarga de un solo argumento ( 17,18 ) no está proporcionada, pero la sobrecarga con tamaño que toma std::size_t como segundo parámetro ( 21,22 ) está disponible, la forma con tamaño es llamada para la desasignación normal, y el runtime de C++ pasa el tamaño del objeto a desasignar como segundo argumento. Si ambas formas están definidas, se llama a la versión sin tamaño.

#include <cstddef>
#include <iostream>
// funciones de desalojo específicas de clase con tamaño
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;
}

Salida posible:

custom delete for size 1
custom delete for size 18

Las sobrecargas de operator delete y operator delete [ ] con parámetros adicionales definidos por el usuario ("formas de colocación", ( 25,26 ) ) también pueden definirse como miembros de clase. Cuando la expresión de colocación new fallida busca la función de colocación delete correspondiente para llamar, comienza la búsqueda en el ámbito de la clase antes de examinar el ámbito global, y busca la función con la firma que coincide con la colocación new :

#include <cstddef>
#include <iostream>
#include <stdexcept>
struct X
{
    X() { throw std::runtime_error("X(): 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
    {
        [[maybe_unused]] X* p1 = new (true) X;
    }
    catch (const std::exception& ex)
    {
        std::cout << ex.what() << '\n';
    }
}

Salida:

custom placement new called, b = 1
custom placement delete called, b = 1
X(): std::runtime_error

Si el operador de eliminación a nivel de clase operator delete es una función plantilla, debe tener el tipo de retorno void , el primer argumento void * , y debe tener dos o más parámetros. En otras palabras, solo las formas de colocación pueden ser plantillas. Una instancia de plantilla nunca es una función de desasignación habitual, independientemente de su firma. La especialización de la plantilla operator delete se selecciona mediante deducción de argumentos de plantilla .

Notas

La llamada al T :: operator delete específico de la clase en una clase polimórfica es el único caso donde una función miembro estática se llama mediante despacho dinámico.

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)
Macro de prueba de características Valor Estándar Característica
__cpp_sized_deallocation 201309L (C++14) Desasignación dimensionada
__cpp_impl_destroying_delete 201806L (C++20) Operador delete destructor (soporte del compilador)
__cpp_lib_destroying_delete 201806L (C++20) Operador delete destructor (soporte de biblioteca)

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 220 C++98 se permitía que las funciones de desasignación definidas por el usuario lanzaran excepciones lanzar desde una función de desasignación
resulta en comportamiento indefinido
CWG 1438 C++98 cualquier uso de un valor de puntero inválido era comportamiento indefinido solo la indirección y desasignación lo son
LWG 206 C++98 reemplazar ( 2 ) no afectaba el comportamiento por defecto de ( 10 ) el comportamiento por defecto
cambia en consecuencia
LWG 298 C++98 reemplazar ( 1 ) no afectaba el comportamiento por defecto de ( 9 ) el comportamiento por defecto
cambia en consecuencia
LWG 404 C++98 los reemplazos de las funciones de desasignación reemplazables
podían declararse inline
prohibido, no se requiere diagnóstico
LWG 2458 C++14 las sobrecargas que toman ( void * , std:: size_t , const
std:: nothrow_t & ) estaban especificadas, pero nunca podían ser llamadas
eliminadas las sobrecargas espurias

Véase también

[static] (C++23)
desasigna memoria previamente obtenida de operator new
(función miembro estática pública de std::generator<Ref,V,Allocator>::promise_type )
funciones de asignación
(función)
(obsoleto en C++17) (eliminado en C++20)
libera almacenamiento no inicializado
(plantilla de función)
desasigna memoria previamente asignada
(función)