删除非类型化shared_ptr

Deleting an untyped shared_ptr

本文关键字:ptr shared 类型化 删除      更新时间:2023-10-16

我正在努力将C++库包装到C桥中。

所有对象,我想在堆上维护shared_ptrs,例如:

void* makeFoo() {
return new shared_ptr<void>(shared_ptr::make_shared<Foo>());
}

我可以使用这样的通用销毁吗:

void destroy(void* p) {
delete static_cast<shared_ptr<void>*> p;
}

还是有更清洁的方法?

delete的参数的类型必须与您要删除的内容的实际类型匹配(例如,否则将如何调用正确的析构函数?(,或者至少是多态层次结构中的基类型,以便虚拟地找到析构函数([expr.delete]/3(。

所以,不,你不能那样做。

这里有两件事在起作用:

  1. 当您致电new SomeType()...然后,您需要调用delete pointer其中pointer具有类型SomeType *并指向该new表达式分配的对象。关于基类,此规则有扩展,但此处不涉及继承,因此我们将不在此进行

  2. shared_ptr<Foo>不仅管理Foo对象,还管理知道如何破坏Foo对象的"删除器"。 当您从另一个shared_ptr构造一个时,该删除器将被传递。 这允许"类型擦除":

    shared_ptr<Foo> typed = make_shared<Foo>();
    shared_ptr<void> erased = typed;
    

    在这里,erased不再具有有关其指向的对象类型的编译时信息(该信息已被"擦除"(,但仍具有有关对象类型的运行时信息(删除器(。

因此,要完成这项工作,您需要确保不会违反上述第1点;您需要delete分配new相同的类型:shared_ptr<void>。 这个shared_ptr<void>需要从shared_ptr<Foo>构造,因为它有一个知道如何破坏Foo的删除器:

void* makeFoo() {
shared_ptr<Foo> with_type = make_shared<Foo>();
shared_ptr<void> type_erased = with_type; // Just for illustration, merge with line below!
return new shared_ptr<void>(type_erased);
}
void destroy(void * ptr) {
shared_ptr<void> * original_ptr = ptr;
delete original_ptr;
}

makeFoo返回指向shared_ptr<void>的指针。只是剥离了类型信息,即void *.

destroy假设它传递了这样的指针。它的删除调用shared_ptr<void>的析构函数。因为shared_ptr<void>具有原始shared_ptr<Foo>的删除器,它知道如何实际破坏对象(Foo(。


旁注:OP的代码更改了很多次,但仍然存在基本的语法错误。这C++无效!!

delete <shared_ptr<void>*> p;

No.没有这种"通用删除"。

替代解决方案:您可以使用动态对象的地址作为键将std::shared_ptr<void>插入到地图中。释放函数可以从映射中擦除共享指针。