C++ 删除boost::bind的原始指针参数
假设我已将堆分配给C++ 删除boost::bind的原始指针参数,c++,memory-management,boost-bind,auto-ptr,boost-function,C++,Memory Management,Boost Bind,Auto Ptr,Boost Function,假设我已将堆分配给A*,我希望将其作为参数传递给boost::bind。 boost::bind保存在boost::functions的一些类似STL的容器中,供以后处理 我想确保销毁STL容器时,A*将被销毁 证明: A* pA = new A(); // some time later container.push_back(boost::bind(&SomeClass::HandleA, this, pA); // some time later container is de
A*
,我希望将其作为参数传递给boost::bind
。
boost::bind
保存在boost::functions
的一些类似STL的容器中,供以后处理
我想确保销毁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, this, pAutoA);
auto_ptr)
auto_ptr pAutoA(pA);
push_back(boost::bind(&SomeClass::HandleA,this,boost::ref(pAutoA));
pAutoA被销毁,删除了基础pA
编辑02
在上面提到的容器中,我需要存储具有不同参数的杂项“回调”。其中一些是指向对象的原始指针。由于代码很旧,我不能总是更改它
编写自己的包装器以将回调存储在容器中是最后的选择(但可能是唯一的选择),因此是赏金。我想你的意思是你有一些函数,让我们称之为f()
它接受一个A*
,然后你用boost::bind
代理它?你能把这个函数改为接受一个boost/TR1shared\u ptr
吗?使用shared\u ptr
(或者,不太可能的是,一个C++98std::auto\u ptr
)应该解决你的生命周期问题
或者,如果无法更改f
本身,则可以创建一个包装器,该包装器接受共享的\u ptr
,拉出原始指针并使用它调用f
。如果您发现自己编写了大量这些包装器,则可以创建一个模板来生成它们,前提是函数签名类似 注意!这太难看了!
我刚刚做了一些概念证明。就我所知,它是按要求做的-但这些东西依赖于const_cast假设。如果你决定在你的程序中使用类似的东西,准备好反复检查你的程序中一直发生的所有复制构造,并使用valgrind验证没有任何泄漏/损坏
诀窍在于定义自己的包装器类,它忽略常量限定符并允许从常量引用的auto_ptr进行auto_ptr所有权转移。如果您尝试复制向量本身,这可能会变得疯狂
因此,请务必仔细阅读有关向量复制语义、自动所有权转移语义,以及最重要的一点——只需使用共享的内容:)
#包括
#包括
#包括
#包括
#包括
类参数\u数据
{
公众:
~parameter_data()
{
std::cout@pmjordan的想法已经朝着正确的方向发展。您回答说您不能使用共享的\u ptr
,因为一旦构建后您就不能收回它的所有权。但这并不完全正确:使用共享的\u ptr
的自定义删除机制,您可以。这是如何做到的:
假设您的A
和f(A*)
的玩具定义如下:
(这将在剩余的shared_ptr
实例中保留有效负载,但对于您的情况,这是可以的,assert()
将覆盖不可用的情况)
现在您可以像这样手动包装f(A*)
:
void f_sp( const boost::shared_ptr<A> & a ) {
f( take( a ) );
}
void f_sp(const boost::shared_ptr&a){
f(取(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;
}
intmain(intargc,char*argv[]){
const boost::shared_ptr a(新的a,opt_delete());
常量boost::函数func=
boost::bind(&f_sp,a);
如果(argc>=2&&*argv[1]='1')//调用'func'
func();
其他的
不要
返回0;
}
使用1
参数执行测试程序将打印
在f(A*)
~A()
如果没有(或任何其他参数),它将打印
~A()
您可以扩展测试线束,首先将func
放入容器中,但它仍然是安全的。在这种情况下,唯一不安全的事情是调用func
多次复制(但随后将触发take()
中的第二个断言)
EDIT:请注意,此机制不是线程安全的。要使其线程安全,您需要为opt_delete
提供一个互斥锁,以便将operator()
与take()
同步,它不需要非常复杂:
class MyContainer : public std::vector<boost::function<void ()> > {
public:
void push_back(boost::function<void ()> f, A *pA)
{ push_back(f); vec.push_back(pA); }
~MyContainer()
{ int s=vec.size; for(int i=0;i<s;i++) delete vec[i]; }
private:
std::vector<A*> vec;
};
class MyContainer:public std::vector{
公众:
无效推回(boost::函数f,A*pA)
{向后推(f);向量向后推(pA)}
~MyContainer()
{int s=vec.size;for(int i=0;iI可以更改f(),但不能将A*更改为shared_ptr-我需要执行boost::bind(boost::ref(auto_ptr_A)),但我不能确保auto_ptr_A会比boost更长寿boost:bindI通常不建议使用auto_ptr
,除非是在特殊情况下。使用shared_ptr
有什么问题是非常嵌套的函数,是遗留代码的一部分。它手动处理*指针内存。由于没有办法释放()共享\u ptr,我不能使用它。相反,我可以在f()的开头释放自动\u ptr。你说没有办法释放共享\u ptr是什么意思?使用boost::shared\u ptr pA(新的A());
在堆上分配内存,然后pA.reset()
释放它。我很困惑。如果f()
显式释放内存,我不明白您为什么需要自动内存管理。直接绑定原始指针是否可以正常工作?这与我之前的情况类似-容器存储存储\u wrapper*,而存储\u wrapper d-tor删除参数\u数据。我尝试了
struct opt_delete {
bool m_delete;
opt_delete() : m_delete( true ) {}
template <typename T>
void operator()( T * t ) {
if ( m_delete ) delete t;
}
};
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();
}
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;
}
class MyContainer : public std::vector<boost::function<void ()> > {
public:
void push_back(boost::function<void ()> f, A *pA)
{ push_back(f); vec.push_back(pA); }
~MyContainer()
{ int s=vec.size; for(int i=0;i<s;i++) delete vec[i]; }
private:
std::vector<A*> vec;
};
template<class T>
void push_back(T *object, void (T::*fptr)(), A *pA)
{
push_back(boost::bind(fptr, object, pA)); vec.push_back(pA);
}