c – 删除boost :: bind的原始指针参数

假设我有堆分配A *,我想将其作为参数传递给boost :: bind.
保存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()同步.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...