如何将析构函数分配给指针
How to assign a destructor to a pointer?
我正在写一个内存管理库,需要显式调用析构函数,在我的设计中,我有一个指针指向对象的析构函数方法,我写的代码是这样的:
void (*p)() = foo.~Foo;
但我有
错误:无法从类型"void(Foo::(((noexcept"转换"Foo::~Foo"键入"void(*(((">
我尝试了其他格式,如void (Foo:: (*p))() noexcept = foo.~Foo;
,但失败了。
那么,将析构函数赋值给指针的正确方法是什么呢?
编辑:在运行时,我的代码不知道堆中的类型,所以我不能使用foo~Foo((。我需要一个适用于所有析构函数的生成指针,这可能吗?
解决方案:使用模板包装器
不允许获取析构函数的地址。
然而,你可以制作一个非常简单的模板函数,并使用它:
template<class T>
void destruct(const T* x) {
x->~T();
}
现在,只需从以下位置获取指针:
destruct<Foo>
如果需要绑定到一个实际对象,可以使用例如std::bind
(或lambda(:
std::bind(&destruct<Foo>, foo_ptr);
请注意,一旦它被绑定,就无法将其转换为原始函数指针。
对不起,您不能。不允许按照[class.dtor]/2:获取析构函数的地址
析构函数用于销毁其类类型的对象不得获取析构函数的地址析构函数可以为
const
、volatile
或const volatile
对象调用。const
和volatile
语义([dcl.type.cv](不应用于对象遭到破坏。当的析构函数最派生的对象开始。
我需要一个适用于所有析构函数的生成指针,这可能吗?
不,不是。就像它不会与任何其他成员功能一样。
要在对象上调用函数,您需要知道该对象的类型。
而且,由于您不能获取析构函数的地址,您甚至不能在"数据库"中存储/注册析构函数。然而,正如Paul所展示的,你可以存储一个函子来完成这项工作。为每个使用中的对象注册这些会有点难看,但当你试图重新发明类型系统时,就会发生这种情况!
我强烈建议不要进行类型擦除(不如进行一些不错的继承?(,不要自己调用析构函数。
请记住,析构函数当然是一个成员函数,因此您需要两个指针:一个用于对象,另一个用于成员函数(本例中为析构函数(的偏移量。
要获取对象的地址很简单,只需使用std::addressof()
即可。
但是,要到达析构函数,您需要一个包装函数来调用给定对象地址的析构函数。因为您不能获取析构函数的地址。
因此,使用Herb Sutter建议的东西(感谢@LightnessRacesinOrbit和@Croolman的评论(:
[](const void* x) { static_cast<const Foo*>(x)->~Foo(); }
- 将指针分配给另一个指针时会发生什么情况?
- C++将一个指针分配给另一个指针时执行的类型检查
- 我似乎无法为指针分配一个数组,然后更改数组的内容
- C++为 void 指针分配一个字符串
- 当我在 C++ 中将派生类的指针分配给指针时,地址会更改
- MPI 集合通信中的指针分配
- 函数指针分配在创建 DLL 后导致错误
- 通过双指针分配指针
- C++编译时使用 constexpr 字符数组指针分配静态数组?
- 我可以直接为指针分配地址吗?如果是,如何做到这一点
- 为什么为char指针分配内存不会截断char序列
- C++指针分配字符数组的地址
- 将 void 指针分配给另一个 void 指针
- 如何将不同的成员函数指针分配给注册类的不同实例?
- 如何为指针分配特定的内存地址?
- C++ - 无法将顶部常量指针分配给另一个非常量指针
- 将指针分配给另一个指针时会发生什么情况?
- 为指向C++中的对象/对象的指针分配堆内存
- 将指针分配给字符串变量中包含的地址
- 当直接分配时,为什么此功能指针分配起作用,而不是与有条件的操作员一起使用