我试图在其中召唤::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
in中的表达式main()
调用析构函数,并释放内存(无需再次调用析构函数)。该::delete p
表达式没有关于对象p
指向的类型的信息,因为它p
是avoid *
,因此无法调用析构函数。