使用智能指针包装 C 创建和销毁函数
Wrapping C create and destroy functions using a smart pointer
我有一些 C API 可以处理对象的创建和销毁,它提供:createObject(...)
和 destroy(...)
。我想将它包装成一些更现代的 construction/destruction 机制,并将它们与智能指针一起使用。我害怕在某些时候我会忘记销毁对象,或者会发生一些异常。
我知道 shared_ptr
的自定义删除函数,但我不能显式调用 new
,因为 createOjbect
函数处理初始化。
在这种情况下我可以使用STL智能指针吗?在这种情况下,我是否必须从头开始实现一个在构造函数中初始化、在析构函数中销毁和引用计数的 class?
std::shared_ptr
is fully capable to create and delete an object with cutstom creator and deleter, but instead of 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.");
}
要管理由上述函数创建的 Foo
实例,只需执行以下操作:
std::shared_ptr<Foo> foo(createObject(32, 3.14), destroy);
使用 std::shared_ptr
is an overhead if you don't wish to share the object's ownership. In this case the 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));
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> >;
现在假设你有一个 C API 包装 Bob
与 Bob* createBob(some_args...)
和 destroyBob(Bob*)
:
using unique_bob=smart_unique_ptr< Bob, destroyBob >;
unique_bob make_unique_bob(some_args args){
return unique_bob( createBob(args) );
}
a unique_bob
可以隐式移动到 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> >;
假设 dtor 签名是 void(T*)
。
在 C++11 中,您必须编写一个新的无状态函数指针调度程序,以实现零开销唯一指针。
为我的案例发布完整的解决方案:
根据@Akira 的建议,我使用共享指针包装它,因为我希望这个对象在许多宫殿和 lambda 中共享:
// coming from some API:
struct SomeStruct;
bool initializedata(SomeStruct **data);
bool destorycdata(SomeStruct **data);
class SomeStructWrapper
{
public:
SomeStructWrapper()
{
SomeStruct* data;
if(initializedata(&data))
{
m_data = std::shared_ptr<SomeStruct>(data, [](SomeStruct* ptr){
destorycdata(&ptr);
});
}
else
{
throw std::runtime_error("Data was not initalized");
}
}
const SomeStruct* operator->() const {return m_data.get();}
SomeStruct* operator->() {return m_data.get();}
private:
std::shared_ptr<SomeStruct> m_data;
};
我有一些 C API 可以处理对象的创建和销毁,它提供:createObject(...)
和 destroy(...)
。我想将它包装成一些更现代的 construction/destruction 机制,并将它们与智能指针一起使用。我害怕在某些时候我会忘记销毁对象,或者会发生一些异常。
我知道 shared_ptr
的自定义删除函数,但我不能显式调用 new
,因为 createOjbect
函数处理初始化。
在这种情况下我可以使用STL智能指针吗?在这种情况下,我是否必须从头开始实现一个在构造函数中初始化、在析构函数中销毁和引用计数的 class?
std::shared_ptr
is fully capable to create and delete an object with cutstom creator and deleter, but instead of 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.");
}
要管理由上述函数创建的 Foo
实例,只需执行以下操作:
std::shared_ptr<Foo> foo(createObject(32, 3.14), destroy);
使用 std::shared_ptr
is an overhead if you don't wish to share the object's ownership. In this case the 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));
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> >;
现在假设你有一个 C API 包装 Bob
与 Bob* createBob(some_args...)
和 destroyBob(Bob*)
:
using unique_bob=smart_unique_ptr< Bob, destroyBob >;
unique_bob make_unique_bob(some_args args){
return unique_bob( createBob(args) );
}
a unique_bob
可以隐式移动到 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> >;
假设 dtor 签名是 void(T*)
。
在 C++11 中,您必须编写一个新的无状态函数指针调度程序,以实现零开销唯一指针。
为我的案例发布完整的解决方案:
根据@Akira 的建议,我使用共享指针包装它,因为我希望这个对象在许多宫殿和 lambda 中共享:
// coming from some API:
struct SomeStruct;
bool initializedata(SomeStruct **data);
bool destorycdata(SomeStruct **data);
class SomeStructWrapper
{
public:
SomeStructWrapper()
{
SomeStruct* data;
if(initializedata(&data))
{
m_data = std::shared_ptr<SomeStruct>(data, [](SomeStruct* ptr){
destorycdata(&ptr);
});
}
else
{
throw std::runtime_error("Data was not initalized");
}
}
const SomeStruct* operator->() const {return m_data.get();}
SomeStruct* operator->() {return m_data.get();}
private:
std::shared_ptr<SomeStruct> m_data;
};