shared_ptr与非指针资源

Joh*_*ing 23 c++ shared-ptr c++11

在C++ 11中是否可以shared_ptr用来控制非指针资源?


可以用来unique_ptr管理非指针资源.这是通过实现自定义删除器类来完成的,该类提供:

  1. typedef {TYPE} pointer;其中{TYPE}是非指针资源类型
  2. operator()(pointer) 它释放了受控资源

...然后unique_ptr使用自定义删除器作为第二个模板参数实例化a .

例如,在Windows下,可以创建一个unique_ptr管理服务控制句柄的程序.此句柄类型不会通过调用释放delete,而是通过调用释放CloseServiceHandle().以下是执行此操作的示例代码:

自定义删除

struct SvcHandleDeleter
{
    typedef SC_HANDLE pointer;
    SvcHandleDeleter() {};

    template<class Other> SvcHandleDeleter(const Other&) {};

    void operator()(pointer h) const
    {
        CloseServiceHandle(h);
    }
};


typedef std::unique_ptr<SC_HANDLE,SvcHandleDeleter> unique_sch;
Run Code Online (Sandbox Code Playgroud)

实例化

unique_sch scm(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS));
Run Code Online (Sandbox Code Playgroud)

是否可以用来shared_ptr控制非指针资源?

根据文档,有shared_ptr构造函数重载提供了提供自定义删除类的方法,但是没有一个构造函数接受的资源类型不是指针或指针周围的包装器.

如何才能做到这一点?

Xeo*_*Xeo 14

可悲的是,shared_ptr的类型擦除需要使其无法与当前的接口来实现正是你想要的.unique_ptr设法做到这一点,因为它有关于实际删除器类型的静态信息,从中可以绘制实际的"指针"类型.在shared_ptr这种情况下,删除类型在类型擦除过程中丢失(这就是为什么你不能在shared_ptr模板中指定它).

另请注意,unique_ptr不提供任何转换构造函数shared_ptr(例如template<class Y> shared_ptr(Y* p)).它不能这样做,因为pointer它不一定是真正的指针类型,因此它不能限制可接受的内容(除非可能通过某些SFINAE std::is_convertible_to或类似的东西......但我离题).

现在,一个明显的解决方法是简单地new使用资源句柄,就像听起来一样愚蠢.:/

std::shared_ptr<SC_HANDLE> sp(new SC_HANDLE(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS)),
    [](SC_HANDLE* p){ ::CloseServiceHandle(*p); delete p; });
Run Code Online (Sandbox Code Playgroud)


ems*_*msr 5

好吧,只要释放了对指针的最后一个引用,shared_ptr就会调用指向对象的析构函数,然后可以释放类包含的任何内容.做一个类可能是这样的:

struct SvcHandle
{
  typedef SC_HANDLE pointer;
  SvcHandle()
  :M_handle(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS))
  { }

  ~SvcHandle()
  {
      CloseServiceHandle(M_handle);
  }
private:
  pointer M_handle;
};
Run Code Online (Sandbox Code Playgroud)

然后只需使用新的SvcHandle创建一个共享指针.句柄的生命周期管理将与shared_ptr - RAII一起使用.

  • 不要使用像`_M_sth`这样的保留标识符. (6认同)