Traté de llamar ::delete
para una clase en el operator delete
mismo. Pero el destructor no se llama.
Definí una clase MyClass
que operator delete
ha sido sobrecargada. Lo global operator delete
también está sobrecargado. El sobrecargado operator delete
de MyClass
llamará al global sobrecargado operator delete
.
class MyClass
{
public:
MyClass() { printf("Constructing MyClass...\n"); }
virtual ~MyClass() { printf("Destroying MyClass...\n"); }
void* operator new(size_t size)
{
printf("Newing MyClass...\n");
void* p = ::new MyClass();
printf("End of newing MyClass...\n");
return p;
}
void operator delete(void* p)
{
printf("Deleting MyClass...\n");
::delete p; // Why is the destructor not called here?
printf("End of deleting MyClass...\n");
}
};
void* operator new(size_t size)
{
printf("Global newing...\n");
return malloc(size);
}
void operator delete(void* p)
{
printf("Global deleting...\n");
free(p);
}
int main(int argc, char** argv)
{
MyClass* myClass = new MyClass();
delete myClass;
return EXIT_SUCCESS;
}
El resultado es:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Real:
Solo hay una llamada al destructor antes de llamar al sobrecargado operator delete
de MyClass
.
Esperado:
Hay dos llamadas al destructor. Uno antes de llamar al sobrecargado operator delete
de MyClass
. Otro antes de llamar a lo global operator delete
.
::delete p;
provoca un comportamiento indefinido ya que el tipo de *p
no es el mismo que el tipo del objeto que se está eliminando (ni una clase base con destructor virtual)
void*
operando está explícitamente mal formado. [expr.delete] / 1 : " El operando será de puntero a tipo de objeto o de tipo de clase. [...] Esto implica que un objeto no puede eliminarse usando un puntero de tipo void porque void no es un tipo de objeto. * "@OP He modificado mi respuesta.
MyClass::operator new()
debe asignar memoria en bruto, de (al menos)size
bytes. No debe intentar construir completamente una instancia deMyClass
. El constructor deMyClass
se ejecuta despuésMyClass::operator new()
. Luego, ladelete
expresión inmain()
llama al destructor y libera la memoria (sin volver a llamar al destructor). La::delete p
expresión no tiene información sobre el tipo dep
puntos de objeto , ya quep
es avoid *
, por lo que no puede invocar al destructor.