簡體   English   中英

std::shared_ptr 自定義引用計數器

[英]std::shared_ptr custom reference counter

我目前正在處理一個代碼,我需要在代碼的多個部分之間靜態共享一個對象的實例。 所以基本上是一個單身人士。 這個實例將被共享,直到沒有人再使用它。 此時我需要在刪除實際實例之前執行一些清理操作。

如果有人在此之后請求共享實例,它將獲得一個新創建的實例,依此類推。

所以我寫了這樣的東西:

template<typename F>
struct static_filter
{
  template<typename ...Args>
  static std::shared_ptr<F> get(Args... a)
  {
    return _inst = _inst ?: std::shared_ptr<F>(new F(a...));
  }

  static void cleanup()
  {
    // some cleanup operation over inst
    _inst.reset();
  }

private:
  static std::shared_ptr<F> _inst;
};

template<typename F> std::shared_ptr<F> static_filter<F>::_inst{nullptr};

現在我正在尋找一種自動檢測何時沒有人使用 _inst 的方法。 基本上,每次 _inst 的 use_count() 下降到 1 時,我都想得到一個回調。此時我將能夠清理和重置。

我想避免為此實現我自己的引用計數(應用程序在任何地方都使用 shared_ptr 並且更改為自定義類型會有點煩人)。

我嘗試在我的實例上使用自定義刪除器,大致如下:

template<typename F>
struct static_filter
{
  template<typename ...Args>
  static std::shared_ptr<F> get(Args... a)
  {
    return _inst = _inst ?: std::shared_ptr<F>(new F(a..., **static_filter<F>::cleanup**));
  }

  static void cleanup()
  {
    // some cleanup operation over inst
    _inst.reset();
  }

private:
  static std::shared_ptr<F> _inst;
};

template<typename F> std::shared_ptr<F> static_filter<F>::_inst{nullptr};

但顯然這不起作用,因為我的參考計數器實際上從未達到 0。

有誰知道是否有辦法使用 shared_ptr 實現這一目標?

謝謝。

您在此處使用shared_ptr在語義級別上是錯誤的。 您不想持有此static變量的所有權,而只想通過它進行觀察。 這是std::weak_ptr的用例。 有了這個靜態變量,您可以觀察對象,如果它存在,則將其作為shared_ptr返回,並且當其他人持有對它的引用時,不會干擾它的銷毀。

這將如下所示:

template<typename F>
struct static_filter
{
  template<typename ...Args>
  static std::shared_ptr<F> get(Args... a)
  {
    // Returns the shared_ptr observed, if it exists and is not expired, empty ptr otherwise
    // is atomic
    auto shared = _inst.lock(); 
    if(!shared) {
        _inst = (shared = std::shared_ptr<F>(new F(a..., **static_filter<F>::cleanup**));
    }
    return shared;
  }

  static void cleanup()
  {
    // Always check if the calling object is really the managed object
    // some cleanup operation over inst
    _inst.reset();
  }

private:
  static std::weak_ptr<F> _inst;
};

template<typename F> std::weak_ptr<F> static_filter<F>::_inst{};

請注意,這不是線程安全的(您之前的代碼也不是線程安全的),因為在指針為空時對get兩個同時調用,都可以看到指針為空,並且都構造了一個F類型的新對象。 您將不得不添加std::lock_guard以避免這種情況。

請注意,即使您可以在use_count == 1上添加回調,這本質上也是不安全的。 這就是為什么std::shared_ptr::unique()從 C++17 開始被棄用並在 C++20 中被刪除(見 這里這里

暫無
暫無

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

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