是否可以在不知道类型的情况下调用析构函数

Is it possible to call the destructor without knowing the type?

本文关键字:情况下 调用 析构函数 类型 不知道 是否      更新时间:2023-10-16

是否可以在不知道类类型的情况下调用对象的析构函数而不使用delete?我问是因为我正在研究一个分配器(为了好玩/练习),并且我正在使用malloc/放置new来构造对象,但是当我去破坏对象时,我很好奇是否有办法在不知道类型的情况下这样做。如果不可能,为什么不呢?唯一的方法是我在示例代码中显示的方式(已注释掉)?

#include <stdio.h>
#include <new>
void* SomeAllocationFunction(size_t size) {
    return malloc(size);
}
class SomeClass{
public:
    SomeClass() {
        printf("Constructedn");
    }
    ~SomeClass() {
        printf("Destructedn");
    }
};
int main(void){
    void* mem = SomeAllocationFunction(sizeof(SomeClass));
    SomeClass* t = new(mem)SomeClass;
    free(t);
    //t->~SomeClass(); // This will call the destructor, is it possible to do this without knowing the class?
    return 0;
}

(我知道我可以调用删除,但请暂时忽略它。

不,如果不知道类型(或知道具有虚拟析构函数的对象基类型之一),这是不可能的。

通常,自定义分配器既不构造也不销毁对象,尽管有些分配器围绕分配器制作模板化包装器,以执行放置新或直接析构函数调用。

(从技术上讲,您可以将一个函数指针与每个分配相关联,该指针最终调用类型的析构函数。但这相当粗略,我不推荐它。

不,在不知道类的情况下不能调用析构函数,因为编译器不知道要调用哪个析构函数。您可以:

  • 使所有对象都继承自具有虚拟析构函数的某个基对象,并使用该基对象指针而不是 void 指针
  • 利用模板
  • 让分配器本身不管理构造函数/析构函数的调用

在非类型化的内存上调用析构函数比在没有类型的情况下调用构造函数(即:放置新)的可能性更大。构造函数和析构函数都是对象的一部分,编译器需要一个类型来知道要调用什么。

截至 C++17 年,这在 std::destroy_at 中成为可能。请参阅 CPP 参考。