删除未键入的 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>
插入到映射中,使用动态对象的地址作为键。释放函数可以从映射中删除共享指针。
这里有两件事在起作用:
当您调用 new SomeType()
... 然后您需要调用 delete pointer
其中 pointer
具有类型 SomeType *
并指向分配的对象通过 new
表达式。关于基础类,这条规则有一些扩展,但这里不涉及继承,所以我们就此打住。
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;
我正在努力将 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>
插入到映射中,使用动态对象的地址作为键。释放函数可以从映射中删除共享指针。
这里有两件事在起作用:
当您调用
new SomeType()
... 然后您需要调用delete pointer
其中pointer
具有类型SomeType *
并指向分配的对象通过new
表达式。关于基础类,这条规则有一些扩展,但这里不涉及继承,所以我们就此打住。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;