使用智能指针包装C创建和销毁函数

bar*_*ar3 6 c c++ pointers cross-language smart-pointers

我有一些处理对象创建和销毁的C API,它提供:createObject(...)destroy(...).我想将它包装成一些更现代的构造/破坏机制,并将它们与智能指针一起使用.我担心在某些时候我会忘记破坏对象,否则会发生一些异常.

我知道自定义删除函数shared_ptr,但我无法显式调用new,因为createOjbect函数处理初始化.

在这种情况下我可以使用STL智能指针吗?从头开始,我是否必须在构造函数中实现初始化类,在析构函数中进行销毁以及在这种情况下引用计数?

Aki*_*ira 8

std::shared_ptr完全能够创建和删除与cutstom创造者和删除器对象,而是中new,你必须使用生成器功能.

我们考虑一下,我们有以下创建者和删除者:

typedef struct {
    int m_int;
    double m_double;
} Foo;

Foo* createObject(int i_val, double d_val) {
    Foo* output = (Foo*)malloc(sizeof(Foo));

    output->m_int = i_val;
    output->m_double = d_val;

    puts("Foo created.");
    return output;
}

void destroy(Foo* obj) {
    free(obj);
    puts("Foo destroyed.");        
}
Run Code Online (Sandbox Code Playgroud)

要管理Foo上述函数创建的实例,只需执行以下操作:

std::shared_ptr<Foo> foo(createObject(32, 3.14), destroy);
Run Code Online (Sandbox Code Playgroud)

std::shared_ptr如果您不希望共享对象的所有权,则使用该开销.在这种情况下,std::unique_ptr要好得多,但对于这种类型,您必须定义一个自定义删除函数,用它可以删除托管Foo实例:

struct FooDeleter {
    void operator()(Foo* p) const {
        destroy(p);
    }
};
using FooWrapper = std::unique_ptr<Foo, FooDeleter>;

/* ... */

FooWrapper foo(createObject(32, 3.14));
Run Code Online (Sandbox Code Playgroud)


Yak*_*ont 6

C++17。

template<auto X> using constant_t=std::integral_constant<std::decay_t<decltype(X)>, X>
template<auto X> constexpr constant_t<X> constant{};
template<class T, auto dtor> using smart_unique_ptr=std::unique_ptr< T, constant_t<dtor> >;
Run Code Online (Sandbox Code Playgroud)

现在假设您有一个BobBob* createBob(some_args...)and包装的 C API destroyBob(Bob*)

using unique_bob=smart_unique_ptr< Bob, destroyBob >;
unique_bob make_unique_bob(some_args args){
  return unique_bob( createBob(args) );
}
Run Code Online (Sandbox Code Playgroud)

aunique_bob可以隐式移动到 a 中shared_ptr<Bob>

一些额外的假设可以使这个在 C++14 中工作:

template<class T, void(*dtor)(T*)> using smart_unique_ptr=std::unique_ptr< T, std::integral_constant<decltype(dtor),dtor> >;
Run Code Online (Sandbox Code Playgroud)

假设 dtor 签名是void(T*).

在 C++11 中,您必须为零开销 unqiue ptr 编写一个新的无状态函数指针调度程序。