简体   繁体   English

为什么shared_ptr没有虚拟描述符? (如何解决这个问题?)

[英]Why doesn't shared_ptr have a virtual descructor? (and how can I get around this?)

I wanted to make a special version of shared_ptr that would perform specific operations when it was created or destroyed, but my plans appear to be foiled by the realization that shared_ptr 's destructor is non virtual, meaning when I override it, my pointers never get cleaned up when the last instance of them are destroyed. 我想制作一个shared_ptr的特殊版本,该版本在创建或销毁它时会执行特定的操作,但是我的计划似乎因为意识到shared_ptr的析构函数是非虚拟的而被挫败了,这意味着当我覆盖它时,我的指针永远不会变当它们的最后一个实例被销毁时进行清理。

The only alternative that comes to mind is to build in this behavior into every class that I want to use with my hypothetical custom shared_ptr , and that's not feasible (or possible in some cases). 我想到的唯一选择是将这种行为内置到我要与假设的自定义shared_ptr一起使用的每个类中,这是不可行的(在某些情况下是可行的)。

Edit: 编辑:

The reason I want this is because I want to use some classes as userdata objects in lua, and I want each one of my objects that I use this way to have a fenv table unique to it that will be cleaned up when all references to the object have been removed. 我想要这个的原因是因为我想在lua中使用某些类作为userdata对象,并且我希望我使用此方法的每个对象都具有一个唯一的fenv表,当对它的所有引用都将被清除。对象已被删除。 I plan on using the address of the pointer as they key into a table that holds the fenv table. 我计划使用指针的地址,因为它们将密钥输入到保存fenv表的表中。

Lets say I have a widget that can have other widgets as children. 可以说我有一个小部件,可以将其他小部件作为子级。 I create two widgets in Lua, then set one as the child of the other and remove all lua references to the child widget (the fact that it's a child is handled in C++). 我在Lua中创建了两个小部件,然后将其中一个设置为另一个小部件,并删除对该子小部件的所有lua引用(这是C ++处理的事实)。 The GC can now run at any time and remove the child. 现在,GC可以随时运行并删除子项。 I don't necessarily want the child to have it's destructor run though, so I want to make it a shared_ptr. 我不一定要让孩子运行析构函数,因此我想使其成为shared_ptr。 That way, C++ objects can still use it after Lua has cleaned it up. 这样,在Lua清理完之后,C ++对象仍然可以使用它。 If I've assigned values or functions to it's fenv I still want to be able to access them. 如果我已经为其fenv分配了值或功能,我仍然希望能够访问它们。 Only when the final reference to my child widget is removed do I want the fenv tabled to be removed totally. 只有在删除对我的子窗口小部件的最终引用时,我才希望完全删除fenv表。

It already has this ability built in without the need to let people do dangerous things like derive from it: 它已经内置了此功能,而无需让人们做一些危险的事情,例如从中衍生出来的事情:

#include <boost/shared_ptr.hpp>
#include <iostream>

/*
 * Done as a function for simplicity.
 * But this can be done in so many ways
 */
void MyCleanup(int* x)
{
    std::cout << "DONE\n";
    delete x;
}

int main()
{
    boost::shared_ptr<int>  x(new int(5), MyCleanup);

}

Problem with deriving: 导出问题:
Just off the top of my head. 就在我头顶上

class X: public shared_ptr<int> { /* STUFF. With a special destructor. */ };

int main()
{
    /* what happens now? Similar to slicing but not quite */
    X                data1(new int(5));
    shared_ptr<int>  data2;
    shared_ptr<int>  data3(data);

    data2 = data1;
}

Just make a wrapper object; 只是做一个包装对象; much easier. 容易得多。 You can have the wrapper object have a shared_ptr instance inside it, and still use the allocation address of the internal object as an index. 您可以使包装器对象内部具有一个shared_ptr实例,并且仍然使用内部对象的分配地址作为索引。 This seems much better than mucking around with derivation or custom cleanup routines, unless I'm missing something. 这似乎比混用派生或自定义清除例程好得多,除非我遗漏了一些东西。

Eg: 例如:

class CWrapsLuaObject
{
    CWrapsLuaObject( LuaObject* pObject )
    { [assign internal ptr, do mapping, etc.] }

    shared_ptr< LuaObject > m_spObject;

    [...]
};

shared_ptr< CWrapsLuaObject > spInstance( new CWrapsLuaObject( pObject ) );

Am I missing why this would not be the easiest solution (not taking anything away from the other suggested solutions, which could also work)? 我是否想知道为什么这不是最简单的解决方案(不要从其他建议的解决方案中删除任何东西,也可以使用)?

You can provide a custom deletion object to be used with the shared_ptr. 您可以提供要与shared_ptr一起使用的自定义删除对象。 If you're trying to stick extra information into the shared_ptr, you may be better putting it into the deletion object. 如果您试图将其他信息粘贴到shared_ptr中,则最好将其放入删除对象中。 It doesn't feel very clean to me, but it works. 它对我来说不是很干净,但是可以。

class ExtraThingToDestroy
{
  public:
   ~ExtraThingToDestroy() { std::cout<<"Destroying the extra thing"<<std::endl; }
};

template<typename T>
class CustomDestructor
{
  public:
    CustomDestructor( ExtraThingToDestroy * v ) : v_(v) {}
    void operator()( T* t ) { delete t; delete v_; }
    ExtraThingToDestroy * v_;
};

main()
{
   shared_ptr<int> ptr( new int, MyExtraDestructor<int>( new ExtraThingToDestroy ) );
   shared_ptr<int> ptr2 = ptr;
   //Now when ptr and all its copies get destroyed, 
   // the ExtraThingToDestroy will get deleted along with the int.
} 

if you derive the class your_shared_ptr from shared_ptr and override the destructor, your destructor should be called in code like this: 如果您从shared_ptr派生出类your_shared_ptr并覆盖了析构函数,则应以如下代码调用析构函数:

{
  your_shared_ptr<int> x(new int);
}

If you use it like this, instead: 如果像这样使用它,则改为:

{
  shared_ptr<int>* ptrptr = new your_shared_ptr<int>(new int);
}

then it won't, but do you really need that? 那就不会了,但是您真的需要吗?

Or am I misunderstanding something? 还是我误会了什么?

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

相关问题 为什么std :: shared_ptr没有运算符 - > *? - Why doesn't std::shared_ptr have operator->*? 为什么我可以将 0 转换为 std::shared_ptr<T> 但不是1? - Why can I convert 0 to an std::shared_ptr<T> but not 1? 为什么std :: unique_ptr没有像std :: shared_ptr这样的别名构造函数? - Why doesn't std::unique_ptr have an aliasing constructor like std::shared_ptr has? 为什么 unique_ptr 将删除器作为类型参数而 shared_ptr 没有? - Why does unique_ptr have the deleter as a type parameter while shared_ptr doesn't? 我可以将0分配给shared_ptr吗? 为什么? - Can I assign 0 to a shared_ptr? Why? 为什么不将shared_ptr <A>隐式转换为shared_ptr <A const>? - Why doesn't shared_ptr<A> implicit convert to shared_ptr<A const>? 我怎样才能`nlohmann::json::get <std::shared_ptr<const t> &gt;`? </std::shared_ptr<const> - How can I `nlohmann::json::get<std::shared_ptr<const T>>`? 为什么我不能添加shared_ptr <Derived> 到地图 <key_type,shared_ptr<Base> &gt;在此代码中? - Why can't I add a shared_ptr<Derived> to a map<key_type,shared_ptr<Base>> in this code? 为什么Qt的qHash()没有std :: shared_ptr的重载? - Why doesn't Qt's qHash() have an overload for std::shared_ptr? 我如何处理 shared_ptr ++ - How can i handle shared_ptr ++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM