扩展auto_ptr以释放C风格的对象

时间:2017-08-03 08:18:19

标签: c++

我想为net-snmp C库struct snmp_pdu对象实现RAII机制。

该对象是使用名为struct snmp_pdu* snmp_pdu_create(int type)的方法创建的,并使用方法void snmp_free_pdu(struct snmp_pdu *obj)发布。

我所做的是扩展auto_ptr以在析构函数中调用方法libname_free_obj。以下是代码:

class auto_snmp_pdu : public std::auto_ptr<snmp_pdu>
{
  public:
   virtual ~auto_snmp_pdu()
   {
     snmp_free_pdu(get());
   }
};

以上是否更正?

修改

我无法使用unique_ptr,因为我使用的是旧版本的g ++,我无权更新它。

2 个答案:

答案 0 :(得分:6)

auto_ptr已被弃用且容易出错。将unique_ptr与自定义删除工具一起使用。这是一个实现:

#include <memory>
extern "C" {
    struct snmp_pdu;

    struct snmp_pdu* snmp_pdu_create(int type);
    void snmp_free_pdu(struct snmp_pdu *obj);
}

struct snmp_pdu_deleter
{
    void operator()(snmp_pdu* p) const noexcept {
        snmp_free_pdu(p);
    }
};
using snmp_pdu_ptr = std::unique_ptr<snmp_pdu, snmp_pdu_deleter>;

snmp_pdu_ptr create_snmp_pdu(int x) {
    return snmp_pdu_ptr(snmp_pdu_create(x));
}


int main()
{
    auto ptr = create_snmp_pdu(0);
}
  
    

但我的编译器是pre-c ++ 11

  

unique_ptrmove语义相当容易模拟:

#include <utility>
#include <iostream>
#include <stdlib.h>

extern "C" {
    struct snmp_pdu {};

    void foo(snmp_pdu*) { std::cout << "foo" << std::endl; }

    struct snmp_pdu* snmp_pdu_create(int type) {
        return (snmp_pdu*)malloc(sizeof(snmp_pdu));
    }
    void snmp_free_pdu(struct snmp_pdu *obj) {
        free(obj);
    }
}

struct snmp_pdu_proxy
{
    struct mover { 
        mover(snmp_pdu*& impl_ref) : impl_ref_(impl_ref) {}
        snmp_pdu*& impl_ref_; 
        };

    snmp_pdu_proxy(int code) 
    : impl_(snmp_pdu_create(code))
    {}

    snmp_pdu_proxy(mover m) 
    : impl_(0)
    {
        std::swap(impl_, m.impl_ref_);
    }

    mover move() {
        return mover ( impl_ );
    }

    snmp_pdu_proxy& operator=(mover m)
    {
        snmp_pdu_proxy tmp = move();
        std::swap(m.impl_ref_, impl_);
        return *this;
    }

    operator snmp_pdu* () const {
        return impl_;
    }

    ~snmp_pdu_proxy() {
        if(impl_) {
            snmp_free_pdu(impl_);
        }
    } 
private:
    snmp_pdu_proxy& operator=(const snmp_pdu_proxy&);
    snmp_pdu* impl_;
};


int main()
{
    snmp_pdu_proxy ptr = snmp_pdu_proxy(0);

    snmp_pdu_proxy p2 = ptr.move();

    ptr = p2.move();

    foo(ptr);
}

答案 1 :(得分:0)

如果你正在使用C ++ 03,那么你肯定无法使用unique_ptr。但是,这并不能证明使用auto_ptr是正确的。它是一个可怕的构造,在语义上充满了问题。例如,它是可复制的,复制操作移动其下的对象。我甚至无法开始描述会导致多少问题。

只需创建自己的类,即可使用RAII为您重新分配。它比你想象的要简单得多。以下是一些例子:

  1. 在我的博客I described a few ways to do this上,即使使用C ++ 03。
  2. 这是一个释放任何内容的SmartHandle类(不幸的是它的C ++ 11)。我用它来制作HDF5。您可以使用仿函数将其更改为适合C ++ 03。
  3. 支持分离/释放对象的
  4. This is a shared_ptr implementation(它不是线程安全的)。我为一个适用于gcc 4.3的项目创建了这个。
  5. 看看这些,你就会明白这个想法。您可以修改这些示例以满足您的需求。

    祝你好运!