new - pointer c++
¿Por qué se invoca "delete operador" cuando llamo "delete" en un puntero nulo? (2)
Al leer las respuestas a esta pregunta , noté que las respuestas ( esto por ejemplo) implican que se puede llamar al operator delete
incluso cuando la instrucción delete
se ejecuta en un puntero nulo.
Así que escribí un pequeño fragmento:
class Test {
public:
void* operator new( size_t ) { /*doesn''t matter*/ return 0; }
void operator delete( void* ptr ) {
ptr; //to suppress warning and have a line to put breakpoint on
}
};
int main()
{
Test* ptr = 0;
delete ptr;
}
y - sorprendentemente para mí - Test::operator delete()
se invoca con ptr
sosteniendo un puntero nulo.
Según tengo entendido, el operator new
asigna memoria y el operator delete
devuelve la memoria al asignador. Si llamo a delete
statement en un puntero nulo, significa que no había ningún objeto detrás del puntero y que no hay memoria para regresar al asignador.
delete
instrucción delete
incluye invocar un destructor. Cuando paso un puntero nulo, el destructor seguramente no se invoca; C ++ se ocupa de eso. Entonces, ¿por qué se invoca la operator delete
en este caso?
El lenguaje en el próximo estándar C ++ 0x (sección 5.3.5 [expr.delete]
) es el siguiente:
Si el valor del operando de la expresión de eliminación no es un valor de puntero nulo, la expresión de eliminación llamará a una función de desasignación (3.7.4.2). De lo contrario, no se especifica si se llamará a la función de desasignación. [Nota: la función de desasignación se llama independientemente de si el destructor para el objeto o algún elemento de la matriz arroja una excepción. - nota final]
Entonces, es un comportamiento no especificado, algunos compiladores pueden llamar al operator delete
cuando se operator delete
un puntero NULL y otros no.
EDITAR: El término función de desasignación utilizada por el estándar parece estar causando cierta confusión. Viene con una referencia. Algún lenguaje clave de 3.7.4.2 [basic.stc.dynamic.deallocation]
que puede ayudar a aclarar:
Si una clase
T
tiene una función de desasignación de miembros llamadaoperator delete
con exactamente un parámetro, entonces esa función es una función de desasignación usual (no colocación).
El estándar también es muy claro que la operator delete
definida por el usuario necesita aceptar un parámetro que es un valor de puntero nulo:
El valor del primer argumento suministrado a una función de desasignación puede ser un valor de puntero nulo; si es así, y si la función de desasignación se proporciona en la biblioteca estándar, la llamada no tendrá efecto.
Pero debido al comportamiento no especificado 5.3.5, no debe confiar en operator delete
se llame a su operator delete
cuando el puntero es nulo.
La eliminación del operador es como cualquier otro operador, ¿por qué no se invocaría? No puede examinar sus argumentos antes de ser invocado.
Esto es como preguntar por qué se invoca el operator+
cuando se agrega 0.