C++ 与非指针资源共享的\u ptr

C++ 与非指针资源共享的\u ptr,c++,c++11,shared-ptr,C++,C++11,Shared Ptr,在C++11中,是否可以使用共享\u ptr来控制非指针资源 可以使用unique\u ptr管理非指针资源。这是通过实现自定义删除器类来实现的,该类提供: typedef{TYPE}指针其中{TYPE}是非指针资源类型 operator()(指针)释放受控资源 …然后使用自定义删除器作为第二个模板参数实例化一个唯一的\u ptr 例如,在Windows下,可以创建一个唯一的\u ptr,用于管理。此句柄类型不是通过调用delete释放的,而是通过调用。下面是执行此操作的示例代码: 自定义删除

在C++11中,是否可以使用
共享\u ptr
来控制非指针资源


可以使用
unique\u ptr
管理非指针资源。这是通过实现自定义删除器类来实现的,该类提供:

  • typedef{TYPE}指针
    其中
    {TYPE}
    是非指针资源类型
  • operator()(指针)
    释放受控资源
  • …然后使用自定义删除器作为第二个模板参数实例化一个
    唯一的\u ptr

    例如,在Windows下,可以创建一个
    唯一的\u ptr
    ,用于管理。此句柄类型不是通过调用
    delete
    释放的,而是通过调用。下面是执行此操作的示例代码:

    自定义删除程序
    是否可以使用
    共享\u ptr
    来控制非指针资源

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


    如何做到这一点?

    好吧,一旦释放指针的最后一个引用,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;
    };
    
    然后用一个新的svchHandle创建一个共享指针。
    句柄的生命周期管理将与共享的\u ptr-RAII一起进行,最好。

    不这样认为。因为标准为共享的\u 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() { }
    
    1后置条件:get()==nullptr。2返回:get()的值在 释放调用的开始


    没有指针资源?你试图破解语言。这总是个坏主意。

    遗憾的是,
    共享的ptr
    对类型擦除的需求使得当前接口无法完全实现您想要的
    unique_ptr
    之所以能够做到这一点,是因为它具有关于实际删除器类型的静态信息,可以从中绘制实际的“指针”类型。在
    shared_ptr
    的情况下,删除器类型在类型擦除过程中丢失(这就是为什么不能在
    shared_ptr
    模板中指定它的原因)

    还请注意,
    unique\u ptr
    不提供任何转换构造函数,如
    shared\u ptr
    提供的(例如
    模板共享\u ptr(Y*p)
    )。它不能这样做,因为
    指针
    不一定是真正的指针类型,因此它不能限制可以接受的内容(除了可能通过一些带有
    std::is\u convertible\u 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; });
    
    std::shared_ptr sp(新的SC_句柄(::OpenSCManagerA(0,0,SC_MANAGER_ALL_ACCESS)),
    [](SC_HANDLE*p){::CloseServiceHandle(*p);删除p;});
    
    这个怎么样

    auto scm = make_shared<unique_sch>(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS));
    
    auto scm=make_shared(::OpenSCManagerA(0,0,SC_MANAGER_ALL_ACCESS));
    
    unique\u sch是您在问题中提到的课程。 现在将scm用作指向资源的共享指针。 在需要的时候取消引用不是最好的办法,但是你问过是否可能

    但它仍然使用指针。 从文档中可以看出,unique_ptr类将指针类作为构造函数参数,实际上可以是任何参数。 shared_ptr但是,将类型作为模板参数,并强制将其转换为指向其构造函数上该类型的指针:

    模板共享\u ptr(Y*ptr,删除类d)


    我认为可以肯定地说,它不能直接用于管理非指针资源,因为共享的ptr类假定其资源是指针。

    不要使用像
    \M\u sth
    这样的保留标识符。这是我使用了大约12年的技术。它在我的个人gizmo库中实现,与您在这里的实现非常相似。我希望消除对这个自定义代码的需要。唉,这似乎是不可能的。不知何故,我在大脑中实现了标准的库容器。我修正了这个例子。@johndilling在标准世界里有一个RAII包装器冒出了泡沫:@emsr:Awesome。谢谢分享。这里是。但是
    SC\u HANDLE
    是指针类型!在
    winsvc.h
    声明句柄(SC\u句柄)
    。在
    winnt.h
    中:
    定义DECLARE\u HANDLE(n)typedef struct n#
    std::unique_ptr
    不同于
    std::unique_ptr
    。更重要的是,有些API中的句柄可以是整型的。@LucDanton:是的,但在OP的特定示例中,它是一个指针。大多数Win32句柄都使用
    DECLARE\u HANDLE
    宏,因此它们在语法上也是指针(但并非都指向实际内存)。这为使用
    std::shared\u ptr
    +1解决OP示例问题提供了可能性:我当然可以这样做,但我想我会重构为使用
    unique\u ptr
    。)
    pointer release() noexcept;
    
    std::shared_ptr<SC_HANDLE> sp(new SC_HANDLE(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS)),
        [](SC_HANDLE* p){ ::CloseServiceHandle(*p); delete p; });
    
    auto scm = make_shared<unique_sch>(::OpenSCManagerA(0, 0, SC_MANAGER_ALL_ACCESS));