【发布时间】:2020-02-17 09:23:15
【问题描述】:
我尝试调用::delete 来获取operator delete 中的一个类。但是没有调用析构函数。
我定义了一个类MyClass,其operator delete 已被重载。全局 operator delete 也被重载。 MyClass 的重载operator delete 将调用重载的全局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...
实际:
在调用MyClass 的重载operator delete 之前,只调用了一次析构函数。
预期:
对析构函数有两个调用。调用MyClass 的重载operator delete 之前的一个。另一个之前打电话给全球operator delete。
【问题讨论】:
-
MyClass::operator new()应该分配(至少)size字节的原始内存。它不应该尝试完全构造MyClass的实例。MyClass的构造函数在MyClass::operator new()之后执行。然后,main()中的delete表达式调用析构函数,并释放内存(不再调用析构函数)。::delete p表达式没有关于p指向的对象类型的信息,因为p是void *,因此无法调用析构函数。 -
已经给你的回答是正确的,但我想知道:为什么你要覆盖 new 和 delete?典型的用例是实现自定义内存管理(GC、不是来自默认 malloc() 的内存等)。也许您使用了错误的工具来实现您想要实现的目标。
-
::delete p;导致未定义的行为,因为*p的类型与被删除对象的类型不同(也不是具有虚拟析构函数的基类) -
@M.M 主要编译器最多只会警告它,所以我没有意识到
void*作为操作数甚至是明确的格式错误。 [expr.delete]/1: "操作数应该是指向对象类型或类类型的指针。[...] 这意味着不能使用 void 类型的指针删除对象,因为 void 不是对象类型。*”@OP 我已经修改了我的答案。
标签: c++ delete-operator