具有非指针资源的shared_ptr
shared_ptr with non-pointer resources
在C++11中,是否可以使用shared_ptr
来控制非指针资源?
可以使用unique_ptr
来管理非指针资源。这是通过实现一个自定义的deleter类来实现的,该类提供:
typedef {TYPE} pointer;
,其中{TYPE}
是非指针资源类型- 释放受控资源的
operator()(pointer)
然后以自定义删除器作为第二模板参数来实例化CCD_ 6。
例如,在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;
实例化
unique_sch scm(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS));
是否也可以使用shared_ptr
来控制非指针资源?
根据文档,shared_ptr
构造函数重载提供了提供自定义deleter类的方法,但没有一个构造函数接受不是指针或指针周围包装的资源类型。
如何做到这一点?
遗憾的是,shared_ptr
对类型擦除的需求使得当前接口无法实现您想要的。unique_ptr
之所以能够做到这一点,是因为它有关于实际deleter类型的静态信息,可以从中绘制实际的"指针"类型。在shared_ptr
的情况下,deleter类型在类型擦除过程中丢失(这就是为什么不能在shared_ptr
模板中指定它)。
还要注意,unique_ptr
不像shared_ptr
那样提供任何转换构造函数(例如template<class Y> shared_ptr(Y* p)
)。它不能这样做,因为pointer
不一定是一个真正的指针类型,所以它不能限制可以接受的内容(除了通过std::is_convertible_to
之类的SFINAE……但我跑题了)。
现在,一个明显的解决方法是简单地new
资源句柄,尽管听起来很愚蠢。:/
std::shared_ptr<SC_HANDLE> sp(new SC_HANDLE(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS)),
[](SC_HANDLE* p){ ::CloseServiceHandle(*p); delete p; });
好吧,一旦对指针的最后一次引用被释放,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;
};
然后用一个新的SvcHandle创建一个共享指针。句柄的终身管理将与shared_ptr-RAII保持最佳状态。
这个怎么样?
auto scm = make_shared<unique_sch>(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS));
unique_sch是您在问题中提到的类。现在使用scm作为指向资源的共享指针。在需要的时候取消引用并不是最好的事情,但你确实问过是否可能。
但这仍在使用指针。从文档中可以看出,unique_ptr类采用指针作为构造函数参数,实际上可以是任何参数。shared_ptr然而,将一个类型作为模板参数,并在其构造函数上将其强制转换为指向该类型的指针
模板<类Y,类Deleter>shared_ptr(Y*ptr,Deleter d);
我认为可以肯定地说,它不能直接用于管理非指针资源,因为shared_ptr类假设其资源是指针。
不要这样想。因为标准为shared_ptr提供了这样的构造函数,而没有其他构造函数。
// 20.7.2.2.1, constructors:
constexpr shared_ptr() noexcept;
template<class Y> explicit shared_ptr(Y* p);
template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d)
template <class D, class A> shared_ptr(nullptr_t p, D d, A a)
template<class Y> shared_ptr(const shared_ptr<Y>& r, T *p) noexcept;
shared_ptr(const shared_ptr& r) noexcept;
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
shared_ptr(shared_ptr&& r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
template<class Y> shared_ptr(auto_ptr<Y>&& r);
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
constexpr shared_ptr(nullptr_t) : shared_ptr() { }
以及你想如何做,例如(对于unique_ptr)
pointer release() noexcept;
1后置条件:get()==nullptr。2返回:get()的值为释放调用的开始。
没有指针资源?你试图破解语言。这总是个坏主意。
- CLANG 编译器 说:变量"PTR"可能未初始化
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 将 ptr 传递给 ptr 到 A 作为参数传递给 A 的函数是不好的做法吗?
- 为共享 ptr 向量实现复制 c'tor?
- 字符和整数中 **(ptr+1) 的值差异
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 如何将派生类从基 ptr 分配给 nlohmann::json
- 引用 std::shared:ptr 以避免引用计数
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 另一种类型的智能ptr,比如具有弱refs的unique_ptr
- 尝试打印出 *ptr++ 的值,以了解它是如何工作的
- 如何控制共享 ptr 引用计数?
- dopen():不以 root 身份运行时"failed to map segment from shared object"
- C++中的指针否定 (!ptr == NULL)
- 从const ptr*转换为ptr*时出现问题
- 无法使用 libtool 将 -shared 参数传递给 g++
- boost::shared_ptr和std::shared-ptr的同居
- 我可以用std::shared_ptr而不是boost::shared-ptr构建boost库吗
- shared-ptr-C++shared_ptr与unique_ptr用于资源管理