dim*_*mba 6 c++ memory-management auto-ptr boost-bind boost-function
假设我已经分配了堆A*,我希望将其作为参数传递给boost::bind.
boost::bind保存以供稍后处理某些STL的容器boost::functions.
我想确保A*在销毁STL容器时销毁.
示范:
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
Run Code Online (Sandbox Code Playgroud)
怎么做到呢?
编辑
也许我想要的不是那么现实.
我有原始指针和函数接收原始指针.通过boost :: bind延迟调用.此时我想要自动内存管理,以防boost :: bind想要执行.我很懒,所以我想使用"准备好"的智能指针解决方案.
std :: auto_ptr看起来像个好人,但是......
auto_ptr<A> pAutoA(pA);
container.push_back(boost::bind(&SomeClass::HandleA, this, pAutoA);
Run Code Online (Sandbox Code Playgroud)
不编译(见这里)
auto_ptr<A> pAutoA(pA);
container.push_back(boost::bind(&SomeClass::HandleA, this, boost::ref(pAutoA));
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
写一个可以"关闭"的删除器:
struct opt_delete {
bool m_delete;
opt_delete() : m_delete( true ) {}
template <typename T>
void operator()( T * t ) {
if ( m_delete ) delete t;
}
};
Run Code Online (Sandbox Code Playgroud)然后,您可以编写一个再次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();
}
Run Code Online (Sandbox Code Playgroud)
(这将使剩余的shared_ptr实例中的有效负载,但对于您的情况,这没关系,并且assert()当不是时覆盖案例).
现在您可以f(A*)像这样手动换行:
void f_sp( const boost::shared_ptr<A> & a ) {
f( take( a ) );
}
Run Code Online (Sandbox Code Playgroud)最后,测试两种情况:
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;
}
Run Code Online (Sandbox Code Playgroud)1将打印带有参数的测试程序
在f(A*)
~A()
如果没有(或任何其他参数),它将打印出来
〜A()
您可以将测试安全带扩展到先放入func容器,但它仍然是安全的.在这种情况下唯一不安全的是func不止一次调用副本(但之后你会触发第二个断言take()).
编辑:请注意,此机制不是线程安全的.为了使线程安全的,你需要提供opt_delete一个互斥体同步operator()使用take().
| 归档时间: |
|
| 查看次数: |
1219 次 |
| 最近记录: |