Я пытался вызвать ::delete
класс в operator delete
этом. Но деструктор не называется.
Я определил класс MyClass
, operator delete
который был перегружен. Глобал operator delete
также перегружен. Перегруженный operator delete
из MyClass
будет вызывать перегруженный глобальный 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;
}
Выход:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Актуально:
Существует только один вызов деструктора перед вызовом перегружен operator delete
из MyClass
.
Ожидаемое:
Есть два вызова деструктора. Один перед вызовом перегружен operator delete
из MyClass
. Еще один, прежде чем назвать глобальным operator delete
.
::delete p;
вызывает неопределенное поведение, так как тип *p
не совпадает с типом удаляемого объекта (ни базовый класс с виртуальным деструктором)
void*
операнд даже явно плохо сформирован. [expr.delete] / 1 : " Операнд должен иметь указатель на тип объекта или тип класса. [...] Это означает, что объект нельзя удалить с помощью указателя типа void, поскольку void не является типом объекта. * "@OP Я исправил свой ответ.
MyClass::operator new()
должен выделять необработанную память, из (как минимум)size
байтов. Он не должен пытаться полностью создать экземплярMyClass
. КонструкторMyClass
выполняется послеMyClass::operator new()
. Затемdelete
выражение inmain()
вызывает деструктор и освобождает память (без повторного вызова деструктора).::delete p
Выражение не имеет никакой информации о типе объектаp
точек на, так какp
этоvoid *
, так что не может вызывать деструктор.