Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 删除boost::bind的原始指针参数_C++_Memory Management_Boost Bind_Auto Ptr_Boost Function - Fatal编程技术网

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/TR1
shared\u ptr
吗?使用
shared\u ptr
(或者,不太可能的是,一个C++98
std::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);
    }