operator delete , operator delete[]
|
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.
-
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 [ ] .
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:
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) |