0

我想制作一个特殊版本,shared_ptr在创建或销毁时执行特定操作,但我的计划似乎因意识到shared_ptr析构函数是非虚拟的而被挫败,这意味着当我覆盖它时,我的指针永远不会被清理当它们的最后一个实例被销毁时。

想到的唯一替代方法是将这种行为构建到我想与我假设的 custom 一起使用的每个类中,shared_ptr这是不可行的(或在某些情况下是可能的)。

编辑:

我想要这个的原因是因为我想在 lua 中使用一些类作为 userdata 对象,并且我希望我使用这种方式的每个对象都有一个唯一的 fenv 表,当所有对对象已被移除。我计划使用指针的地址,因为它们键入包含 fenv 表的表。

假设我有一个小部件,它可以将其他小部件作为子小部件。我在 Lua 中创建了两个小部件,然后将一个设置为另一个的子小部件,并删除对子小部件的所有 lua 引用(它是一个子小部件的事实在 C++ 中处理)。GC 现在可以随时运行并移除子代。我不一定想让孩子运行它的析构函数,所以我想让它成为一个 shared_ptr。这样,在 Lua 清理之后,C++ 对象仍然可以使用它。如果我已经为其 fenv 分配了值或功能,我仍然希望能够访问它们。只有在删除对我的子小部件的最终引用时,我才希望完全删除表中的 fenv。

4

4 回答 4

8

它已经内置了这种能力,而不需要让人们做危险的事情,比如从中派生:

#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);

}

推导问题:
就在我的脑海中。

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;
}
于 2010-09-27T07:19:39.880 回答
4

只需制作一个包装器对象;容易得多。您可以让包装对象在其中包含一个 shared_ptr 实例,并且仍然使用内部对象的分配地址作为索引。除非我遗漏了什么,否则这似乎比使用派生或自定义清理例程要好得多。

例如:

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

    shared_ptr< LuaObject > m_spObject;

    [...]
};

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

我是否错过了为什么这不是最简单的解决方案(不从其他建议的解决方案中拿走任何东西,这也可以工作)?

于 2010-09-27T07:26:48.363 回答
1

您可以提供与 shared_ptr 一起使用的自定义删除对象。如果您尝试将额外信息粘贴到 shared_ptr 中,则最好将其放入删除对象中。我觉得它不是很干净,但它确实有效。

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.
} 
于 2010-09-27T07:15:52.087 回答
0

如果你从 shared_ptr 派生类 your_shared_ptr 并覆盖析构函数,你的析构函数应该在这样的代码中调用:

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

如果您像这样使用它,请改为:

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

那么它不会,但你真的需要吗?

还是我误解了什么?

于 2010-09-27T06:56:20.927 回答