假设我有堆分配A *,我想将其作为参数传递给boost :: bind.
保存boost :: bind以便稍后在某些STL中处理,比如boost :: functions的容器.
保存boost :: bind以便稍后在某些STL中处理,比如boost :: functions的容器.
我想确保在销毁STL容器时销毁A *.
示范:
A* pA = new A(); // some time later container.push_back(boost::bind(&SomeClass::HandleA,this,pA); // some time later container is destroyed => pA is destroyed too
怎么做到呢?
编辑
也许我想要的不是那么现实.
我有原始指针和函数接收原始指针.通过boost :: bind延迟调用.此时我想要自动内存管理,以防boost :: bind想要执行.我很懒,所以我想使用“准备好”的智能指针解决方案.
std :: auto_ptr看起来像个好人,但是……
auto_ptr<A> pAutoA(pA); container.push_back(boost::bind(&SomeClass::HandleA,pAutoA);
不编译(见here)
auto_ptr<A> pAutoA(pA); container.push_back(boost::bind(&SomeClass::HandleA,boost::ref(pAutoA));
pAutoA被破坏,删除了底层的pA.
编辑02
在上面提到的容器中,我将需要使用不同的参数存储misc“回调”.其中一些是对象的原始指针.由于代码是旧的,我并不总是可以改变它.
编写自己的包装器来存储容器中的回调是最后的手段(可能是唯一的),因此是赏金.
解决方法
@pmjordan的想法已经朝着正确的方向发展.您回复说您不能使用shared_ptr,因为一旦构造,您就无法取回所有权.但这并不完全正确:使用shared_ptr的自定义删除机制,您可以.这是如何:
假设你的A和f(A *)的这些玩具定义:
struct A { ~A() { std::cout << "~A()" << std::endl; } }; void f( A * a ) { std::cout << "in f(A*)" << std::endl; delete a; }
struct opt_delete { bool m_delete; opt_delete() : m_delete( true ) {} template <typename T> void operator()( T * t ) { if ( m_delete ) delete t; } };
>然后你可以编写一个take()函数,它再次获得shared_ptr有效负载的所有权:
template <typename T> T * take( const boost::shared_ptr<T> & sp ) { opt_delete * d = boost::get_deleter<opt_delete>( sp ); assert( d ); assert( d->m_delete == true ); d->m_delete = false; return sp.get(); }
(这会将有效负载留在剩余的shared_ptr实例中,但对于您的情况,这没关系,并且assert()覆盖了不支持的情况).
>现在你可以像这样手动包装f(A *):
void f_sp( const boost::shared_ptr<A> & a ) { f( take( a ) ); }
>最后,测试两种情况:
int main( int argc,char * argv[] ) { const boost::shared_ptr<A> a( new A,opt_delete() ); const boost::function<void()> func = boost::bind( &f_sp,a ); if ( argc >= 2 && *argv[1] == '1' ) // call 'func' func(); else ; // don't return 0; }
将打印执行带有1参数的测试程序
in f(A*)
~A()
如果没有(或任何其他参数),它将打印出来
~A()
您可以扩展测试工具以首先将func放入容器中,但它仍然是安全的.在这种情况下唯一不安全的是多次调用func副本(但是你会在take()中触发第二个断言).
编辑:请注意,此机制不是线程安全的.要使其成为线程安全的,您需要为opt_delete提供一个互斥锁,以使operator()与take()同步.