C++ 需要指针地址的共享\u ptr的自定义删除程序

C++ 需要指针地址的共享\u ptr的自定义删除程序,c++,boost,shared-ptr,C++,Boost,Shared Ptr,许多C API提供的发布函数采用**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,我可以这

许多C API提供的发布函数采用
**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

用法:

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::共享\u ptr frame\u句柄(::av\u frame\u alloc()
,arg_ref_适配器(::av_frame_free));
//用frame_handle.get()做一些事情
//当frame\u处理时,将使用::av\u frame\u free()释放资源
//超出范围。

将指针设置为null是毫无意义的,因为
共享\u ptr
已经保证指针在销毁后不再可见。因此,代码只需传递一个地址即可满足
av\u frame\u free
功能。我建议简单地编写一个函数对象,它传递参数的地址

template <typename Fun>
struct address_of_arg_wrapper {
public:
    address_of_arg_wrapper(Fun fun) : fun(fun) {}

    template <typename P>
    void operator()(P ptr) {
        fun(&ptr);
    }

private:
    typename boost::decay<Fun>::type fun;
};

在我看来,您应该键入def boost::shared_ptr,因为C++11有std::shared_ptr,并且您希望在升级编译器时尽量减少迁移工作。@Bathsheba我只想清除名称空间。将boost::shared_ptr批量替换为std::shared_ptr只需一秒钟。混用名称空间是危险的。@billz:那很酷;只要我们牢记迁移,我就在考虑是否要提及
boost::shared_ptr
std::shared_ptr
的区别,但我认为这不是真正的重点。使用Boost显然可以从Boost获得解决方案(a-la
Boost::ref
),是的!这就是我试图做的,但没能完全做到:-)。Re:空值,这确实是一个API,而不是一个需求。为什么要使用
boost::decay
,而不仅仅是
Fun
?另外,Boost中没有类似的东西吗?@AdiShavit:用于将
Fun
表示为
void()
,而不必使用
void(&)(
)。这与
boost::function
的用户所期望的语法相同。@Tanner Sansbury:对不起,我不明白你的答案。
#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.
template <typename Fun>
struct address_of_arg_wrapper {
public:
    address_of_arg_wrapper(Fun fun) : fun(fun) {}

    template <typename P>
    void operator()(P ptr) {
        fun(&ptr);
    }

private:
    typename boost::decay<Fun>::type fun;
};
[](AVFrame* ptr) { av_frame_free(&ptr); }