Namespaces
Variants

delete expression

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
delete expression
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Destruye objeto(s) previamente asignados por la expresión new y libera el área de memoria obtenida.

Contenidos

Sintaxis

:: (opcional) delete expresión (1)
:: (opcional) delete[] expresión (2)
expression - uno de los siguientes:
1) Destruye un objeto no-array creado por una new-expression .
2) Destruye un array creado por una new[]-expression .

Explicación

Dado el puntero evaluado a partir de expression (después de posibles conversiones) como ptr .

1) ptr debe ser uno de
  • un puntero nulo,
  • un puntero a un objeto no-array creado por una new-expression , o
  • un puntero a un subobjeto base de un objeto no-array creado por una new-expression .
El tipo apuntado por ptr debe ser similar al tipo del objeto (o de un subobjeto base). Si ptr es cualquier otra cosa, incluyendo si es un puntero obtenido por la forma de array de new-expression , el comportamiento es undefined .
2) ptr debe ser un puntero nulo o un puntero cuyo valor fue obtenido previamente por una forma de array de new-expression cuya allocation function no era una forma no asignadora (es decir, sobrecarga (10) ).
El tipo apuntado por ptr debe ser similar al tipo de elemento del objeto array. Si ptr es cualquier otra cosa, incluyendo si es un puntero obtenido por la forma no-array de new-expression , el comportamiento es undefined .

El resultado de la expresión delete siempre tiene tipo void .

Si el objeto que se está eliminando tiene un tipo de clase incompleto en el punto de eliminación, y la clase completa tiene un destructor no trivial o una función de desasignación, el comportamiento es indefinido (hasta C++26) el programa está mal formado (desde C++26) .

Si ptr no es un puntero nulo y la función de desasignación no es un delete destructor (desde C++20) , la expresión delete invoca el destructor (si existe) para el objeto que está siendo destruido, o para cada elemento del array que está siendo destruido (procediendo desde el último elemento al primer elemento del array). El destructor debe ser accesible desde el punto donde aparece la expresión delete.

Después de eso, independientemente de si alguna excepción fue lanzada por cualquier destructor, la expresión delete invoca la función de desasignación : ya sea operator delete (primera versión) o operator delete [ ] (segunda versión) , a menos que la expresión new correspondiente se combinara con otra expresión new (since C++14) .

El nombre de la función de desasignación se busca en el ámbito del tipo dinámico del objeto apuntado por ptr , lo que significa que las funciones de desasignación específicas de la clase, si están presentes, se encuentran antes que las globales. Si :: está presente en la expresión delete, solo el espacio de nombres global es examinado por esta búsqueda. En cualquier caso, cualquier declaración que no sea de funciones de desasignación usuales es descartada.

Si se encuentra cualquier función de desasignación, la función a llamar se selecciona de la siguiente manera (ver función de desasignación para una descripción más detallada de estas funciones y sus efectos):

  • Si al menos una de las funciones de desasignación es un destroying delete, todos los deletes no destructivos son ignorados.
(since C++20)
  • Si el requisito de alineación del tipo excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , las funciones de desasignación conscientes de alineación (con un parámetro de tipo std::align_val_t ) son preferidas. Para otros tipos, las funciones de desasignación no conscientes de alineación (sin un parámetro de tipo std::align_val_t ) son preferidas.
  • Si se encuentran más de una función preferida, solo las funciones preferidas son consideradas en el siguiente paso.
  • Si no se encuentran funciones preferidas, las no preferidas son consideradas en el siguiente paso.
  • Si solo queda una función, esa función es seleccionada.
(since C++17)
  • Si las funciones de desasignación encontradas son específicas de la clase, la función de desasignación específica de la clase sin información de tamaño (sin un parámetro de tipo std::size_t ) tiene preferencia sobre la función de desasignación específica de la clase con información de tamaño (con un parámetro de tipo std::size_t ).
  • De lo contrario, la búsqueda alcanza el ámbito global, y:
  • Si el tipo es completo y si, solo para la forma de array, el operando es un puntero a un tipo de clase con un destructor no trivial o un array (posiblemente multidimensional) del mismo, se selecciona la función global de desasignación con tamaño (con un parámetro de tipo std::size_t ).
  • De lo contrario, no está especificado si se selecciona la función global de desasignación con tamaño (con un parámetro de tipo std::size_t ) o la función global de desasignación sin tamaño (sin un parámetro de tipo std::size_t ).
(desde C++14)

La función de desasignación seleccionada debe ser accesible desde el punto donde aparece la expresión delete, a menos que la función de desasignación sea seleccionada en el punto de definición del tipo dinámico ’s destructor virtual .

El puntero al bloque de almacenamiento a liberar se pasa a la función de desasignación que fue seleccionada por el proceso anterior como primer argumento. El tamaño del bloque se pasa como el argumento opcional std::size_t . El requisito de alineación se pasa como el argumento opcional std::align_val_t . (desde C++17)

Si ptr es un valor de puntero nulo, no se llaman a los destructores, y la función de desasignación puede o no ser llamada (no está especificado), pero las funciones de desasignación por defecto están garantizadas para no hacer nada cuando se les pasa un puntero nulo.

Si ptr es un puntero a un subobjeto de clase base del objeto que fue asignado con new , el destructor de la clase base debe ser virtual , de lo contrario el comportamiento es indefinido.

Notas

Un puntero a void no puede ser eliminado porque no es un puntero a un tipo de objeto.

Debido a que un par de corchetes que sigue a la palabra clave delete siempre se interpreta como la forma de array de una expresión delete, una expresión lambda con una lista de captura vacía inmediatamente después de delete debe estar encerrada entre paréntesis.

// delete []{ return new int; }(); // error de análisis
delete ([]{ return new int; })();  // OK
(desde C++11)

Palabras clave

delete

Informes de defectos

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

DR Se aplica a Comportamiento publicado Comportamiento correcto
CWG 288 C++98 para la primera forma, se comparaba el tipo estático del
operando con su tipo dinámico
comparar el tipo estático del objeto
a eliminar con su tipo dinámico
CWG 353 C++98 no se especificaba si la función de desasignación se invocaría si
el destructor lanzaba una excepción
siempre se invoca
CWG 599 C++98 la primera forma podía aceptar un puntero nulo de
cualquier tipo, incluyendo punteros a función
excepto punteros a tipos objeto,
se rechazan todos los demás tipos de puntero
CWG 1642 C++98 expression podría ser un lvalue de puntero no permitido
CWG 2474 C++98 eliminar un puntero a un objeto de un tipo similar pero
diferente resultaba en comportamiento indefinido
se define correctamente
CWG 2624 C++98 los punteros obtenidos de operator new [ ] no asignador podían pasarse a delete [ ] prohibido
CWG 2758 C++98 no estaba claro cómo se realizaba el control de acceso para
la función de desasignación y el destructor
se aclara

Véase también