簡體   English   中英

shared_ptr與非指針資源

[英]shared_ptr with non-pointer resources

在C ++ 11中,是否可以使用shared_ptr來控制非指針資源?


可以使用unique_ptr來管理非指針資源。 這是通過實現自定義刪除器類來完成的,該類提供:

  1. 一個typedef {TYPE} pointer; 其中{TYPE}是非指針資源類型
  2. operator()(pointer)釋放受控資源

...然后使用自定義刪除器作為第二個模板參數實例化unique_ptr

例如,在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構造函數重載 ,它提供了提供自定義刪除器類的方法,但是沒有一個構造函數接受的資源類型不是指針或指針周圍的包裝器。

如何才能做到這一點?

可悲的是, shared_ptr的需求類型擦除使得它無法與當前的接口來實現想要什么。 unique_ptr設法做到這一點,因為它有關於實際刪除器類型的靜態信息,從中可以繪制實際的“指針”類型。 shared_ptr的情況下,刪除類型在類型擦除過程中丟失(這就是為什么你不能在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將一個類型作為模板參數,並在其構造函數中強制將其轉換為指向該類型的指針:

template <class Y,class 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()在釋放調用開始時的值。

沒有指針資源? 你試圖破解語言。 這總是壞主意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM