Я намагався закликати ::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
вираз уmain()
виклику деструктора і звільняє пам'ять (не викликаючи знову деструктора).::delete p
Вираз не має ніякої інформації про тип об'єктаp
точок на, так якp
цеvoid *
, так що не може викликати деструктор.