简体   繁体   English

如何将析构函数分配给指针?

[英]How to assign a destructor to a pointer?

I'm writing a memory management library and need to call a destructor explicitly, in my design I have a pointer which points to the destuctor method of a object, I write code like this:我正在编写一个 memory 管理库,需要显式调用析构函数,在我的设计中,我有一个指向 object 的析构函数方法的指针,我编写如下代码:

void (*p)() = foo.~Foo;

but I got但我得到了

error: cannot convert 'Foo::~Foo' from type 'void (Foo::)() noexcept' to type 'void (*)()'错误:无法将 'Foo::~Foo' 从类型 'void (Foo::)() noexcept' 转换为类型 'void (*)()'

I tried some other format like void (Foo:: (*p))() noexcept = foo.~Foo;我尝试了其他一些格式,例如void (Foo:: (*p))() noexcept = foo.~Foo; but failed.但失败了。

So what is the right way to assignment a destructor to a pointer?那么将析构函数分配给指针的正确方法是什么?

Edit: at runtime my code do not know what a type it is in my heap, so I can't use foo.~Foo().编辑:在运行时我的代码不知道它在我的堆中是什么类型,所以我不能使用 foo.~Foo()。 I need a generate pointer which fits for all destructors, is this possible?我需要一个适合所有析构函数的生成指针,这可能吗?

Solution: Use a template wrapper解决方案:使用模板包装器

Taking the address of the destructor isn't allowed.不允许使用析构函数的地址。

However you can just make a very simple template function and use that instead:但是,您可以制作一个非常简单的模板 function 并使用它来代替:

template<class T>
void destruct(const T* x) {
    x->~T();
}

Now instead, just obtain the pointer from:现在,只需从以下位置获取指针:

destruct<Foo>

You can use eg.您可以使用例如。 std::bind (or a lambda) if you need to bind to an actual object:如果您需要绑定到实际的 object,请使用std::bind (或 lambda):

std::bind(&destruct<Foo>, foo_ptr);

Please note that once it is bound , it cannot be converted to a raw function pointer.请注意,一旦绑定,它就不能转换为原始的 function 指针。

Sorry, you can't.对不起,你不能。 You are not allowed to take the address of a destructor per [class.dtor]/2 :您不能根据[class.dtor]/2 获取析构函数的地址:

A destructor is used to destroy objects of its class type.析构函数用于销毁其 class 类型的对象。 The address of a destructor shall not be taken.不应采用析构函数的地址。 A destructor can be invoked for a const , volatile or const volatile object.可以为constvolatileconst volatile object 调用析构函数。 const and volatile semantics ([dcl.type.cv]) are not applied on an object under destruction. constvolatile语义 ([dcl.type.cv]) 不适用于正在破坏的 object。 They stop being in effect when the destructor for the most derived object starts.当派生最多的 object 的析构函数启动时,它们停止生效。

I need a generate pointer which fits for all destructors, is this possible?我需要一个适合所有析构函数的生成指针,这可能吗?

No, it is not.不它不是。 Like it would not be with any other member function.就像它不会与任何其他成员 function 一样。

To call a function on an object, you need to know the type of that object.要在 object 上调用 function,您需要知道 object 的类型。

And, since you cannot take the address of a destructor, you cannot even store/register one in a "database".而且,由于您无法获取析构函数的地址,因此您甚至无法在“数据库”中存储/注册一个。 However, as Paul showed, you can store a functor to do the job.然而,正如 Paul 所展示的,您可以存储一个函子来完成这项工作。 It'll be a bit ugly to register these for each object in use, but that's what happens when you try to reinvent the type system!为每个正在使用的 object 注册这些会有点难看,但是当您尝试重新发明类型系统时会发生这种情况!

I strongly advise moving away from type erasure (how about some nice inheritance instead?), and moving away from calling destructors yourself.我强烈建议不要使用类型擦除(改用一些不错的 inheritance 怎么样?),不要自己调用析构函数。

Remember that the destructor is, of course, a member function so you'll need two pointers: one for the object and one for the offset of the member function (the destructor in this case).请记住,析构函数当然是成员 function,因此您需要两个指针:一个指向 object,一个指向成员 ZC1C425268E68385D1AB5074C17A94F4 的偏移量(在这种情况下为析构函数)。

To get the object's address is trivial, simply use std::addressof() .要获取对象的地址很简单,只需使用std::addressof()

But to get to the destructor you'll need a wrapper function to invoke the destructor given the object's address because you can't take the address of a destructor.但是要获得析构函数,您需要一个包装器 function 来调用给定对象地址的析构函数,因为您不能获取析构函数的地址。

So use something like Herb Sutter suggests (thanks to @LightnessRacesinOrbit's and @Croolman's comments):所以使用像Herb Sutter建议的东西(感谢@LightnessRacesinOrbit 和@Croolman 的评论):

[](const void* x) { static_cast<const Foo*>(x)->~Foo(); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM