[英]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.