删除未键入的 shared_ptr

Deleting an untyped shared_ptr

我正在努力将 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).

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

没有。没有这样的"generic delete"。

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

这里有两件事在起作用:

  1. 当您调用 new SomeType() ... 然后您需要调用 delete pointer 其中 pointer 具有类型 SomeType * 并指向分配的对象通过 new 表达式。关于基础类,这条规则有一些扩展,但这里不涉及继承,所以我们就此打住。

  2. shared_ptr<Foo> 不仅管理 Foo 对象,而且还管理知道如何销毁 Foo 对象的 "deleter"。当您从另一个构造一个 shared_ptr 时,该删除器将被传递。这允许 "type erasure":

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

    在这里,erased 不再有关于它指向的对象类型的编译时信息(该信息是 "erased"),但仍然有关于对象类型的运行时信息(删除器)对象的类型。

因此,要实现此功能,您需要确保不违反上述第 1 点;您需要 delete 您分配给 new 的同一类型:a 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 returns 指向 shared_ptr<void> 的指针。只是删除了类型信息,即 void *.

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


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

delete <shared_ptr<void>*> p;