许多C API提供释放函数,这些函数使用
我想用自定义删除器的
以下是FFMPEG示例:
为了利用RAII,我可以这样重写:
请注意,
这种方法要求我分别保存资源和释放器,这有几个缺点:
或者
**p
参数来释放资源并将指针设置为NULL
。我想用自定义删除器的
boost::shared_ptr
包装此类C API调用。以下是FFMPEG示例:
AVFrame* frame = av_frame_alloc(); // allocate resource
// Do stuff with frame
av_frame_free(&frame) // free resource
为了利用RAII,我可以这样重写:
AVFrame* frame = av_frame_alloc();
boost::shared_ptr<AVFrame*> frame_releaser(&frame, av_frame_free);
// Do stuff with frame
请注意,
shared_ptr<>
是类型为 <AVFrame*>
而不是指针类型的 <AVFrame>
。这种方法要求我分别保存资源和释放器,这有几个缺点:
frame
可能会被外部更改,导致泄漏。- 它需要两个变量而不是一个,这使代码更容易出错。
我想使用单个 shared_ptr
变量来同时保存资源并在需要时释放它。
与 boost::ref
的精神相似,我正在寻找编写或使用通用的 address_of_arg_wrapper
用于删除器,以便我可以编写类似以下内容的代码:
boost::shared_ptr<AVFrame> frame_handle(av_frame_alloc(), address_of_arg_wrapper(av_frame_free));
// Do stuff with frame_handle.get()
或者
boost::shared_ptr<AVFrame> frame_handle(av_frame_alloc(), address_of_arg_wrapper<av_frame_free>());
// Do stuff with frame_handle.get()
重要的是,包装器必须是通用的,并接受任何指针(ref)类型,以便可以与任何此类API函数一起使用。
我也不想指定类型。
Boost是否有这样的实用程序?
如果没有,那么如何编写这样一个通用的函数对象?
编辑 - 为完整性提供解决方案:
此解决方案基于@R. Martinho Fernandes下面的答案。
- 它包括一个模板函数来创建模板函数对象,因此无需指定模板类型。
- 代码依赖于
boost::decay
。对于我测试的简单情况,只持有一个Fun fun;
成员的版本也起作用。 - 我将名称更改为
arg_ref_adaptor()
。欢迎提出更好的名称建议!
以下是代码:
#include <boost\type_traits\decay.hpp>
//////////////////////////////////////////////////////////////////////////
// Given a function or callable type 'fun', returns an object with
// a void operator(P ptr) that calls fun(&ptr)
// Useful for passing C API function as deleters to shared_ptr<> which require ** instead of *.
template <typename Fun>
struct arg_ref_adaptor_functor
{
public:
arg_ref_adaptor_functor(Fun fun): fun(fun) {}
template <typename P>
void operator()(P ptr)
{ fun(&ptr); }
private:
typename boost::decay<Fun>::type fun;
};
template <typename Fun>
inline arg_ref_adaptor_functor<Fun> arg_ref_adaptor(Fun fun)
{ return arg_ref_adaptor_functor<Fun>(fun); }
使用方法:
boost::shared_ptr<AVFrame> frame_handle(::av_frame_alloc()
,arg_ref_adaptor(::av_frame_free));
// Do stuff with frame_handle.get()
// The resource will be released using ::av_frame_free() when frame_handle
// goes out of scope.
boost::shared_ptr
和std::shared_ptr
,但我决定这并不是重点。使用Boost使人们明显地看到,来自Boost的解决方案(例如boost::ref
)是可以接受的。 - Adi Shavit