簡體   English   中英

將 std::weak_ptr 傳遞給函數有用嗎?

[英]Is it useful to pass std::weak_ptr to functions?

我正在閱讀 Herb Sutter 的這篇關於將智能指針傳遞給函數的文章。 他沒有提到std::weak_ptr ,老實說,我找不到傳遞這種智能指針很有用的好場景。

該功能是否擁有所有權? 通過std::shared_ptr 函數是否只需要對底層對象進行操作? 傳遞原始指針或引用。

那么將std::weak_ptr傳遞給函數是否 100% 沒用?

那么將std::weak_ptr傳遞給函數是否 100% 沒用?

不。

考慮這個玩具示例。

struct PointerObserver
{
    std::weak_ptr<int> held_pointer;

    void observe( std::weak_ptr<int> p )
    {
        held_pointer = std::move(p);
    }

    void report() const
    {
        if ( auto sp = held_pointer.lock() )
        {
            std::cout << "Pointer points to " << *sp << "\n";
        }
        else
        {
            std::cout << "Pointer has expired.\n";
        }
    }
};

在這個例子中,成員函數observe保存傳遞給它的數據 這通常稱為“接收器參數”。

它的weak_ptr參數表示這個傳遞的指針不擁有,但保留稍后擁有的能力,安全地檢測指針是否已過期。

作為一個不同的例子,一個為以后保存狀態的函數可以在多線程上下文中有用地接收一個weak_ptr參數,其中關聯的數據可能會在函數工作時過期

如果您的客戶有一個weak_ptr ,並且您的邏輯可以鎖定或不鎖定它,並且無論如何都有效,那么傳遞一個weak_ptr

作為一個具體的簡單例子:

mutable std::mutex m_mutex;
mutable std::vector<std::weak_ptr<std::function<void(int)>>> m_callbacks;

void clean_callbacks(int x) {
  auto l = std::unique_lock<std::mutex>(m_mutex);
  auto it = std::remove_if( begin(m_callbacks), end(m_callbacks), [](auto w){ return !w.lock(); } );
  m_callbacks.erase( it, end(m_callbacks) );
}
void call_callbacks() {
  clean_callbacks();
  auto tmp = [&]{
    auto l = std::unique_lock<std::mutex>(m_mutex);
    return m_callbacks;
  }();
  for (auto&& wf:tmp) {
    if(auto sf = wf.lock()) {
      (*sf)(x);
    }
  }
}

clean_callbacks有一個接受weak_ptr的 lambda。 它用於刪除任何生命周期已結束的m_callbacks

此代碼用於一個簡單的廣播器,其中廣播發生的頻率遠高於偵聽器失效的頻率,因此等待下一次廣播以消除死偵聽器是一個很好的策略。

弱指針可用於保存以后可能不可用的對象(不延長其生命周期)。 這意味着它們通常用於存儲在容器(或變量)中。 通常會傳遞一個共享指針,直到對象被存儲,然后轉換為弱指針。 然后在使用時必須首先將它們轉換為共享指針,以檢查它們是否仍然有效。 因此,除了作為存儲和檢索過程的一部分(可能在輔助函數中)之外,您不太可能傳遞弱指針。

我可以想出的唯一好處是將 std::weak_ptr 而不是 std::shared_ptr 作為函數中的參數,是該函數負責檢查指針是否有效,從而減少了函數外的任何檢查.

bool function(std::weak_ptr _obj)
{
    if(std::shared_ptr obj = _obj.lock())
    {
        obj->doSomething();
        return true;
    }
    return false
 }

使用 std::shared_ptr 作為參數,則不需要檢查,但在調用函數之前需要從 std:weak_ptr 轉換為 std::shared_ptr。 但是,如果存在傳遞 nullptr 的風險,則也需要對其進行檢查。

void function(std::shared_ptr _obj)
{
    _obj->doSomething();
}

因此,如果從應用程序的許多不同位置多次將 std::weak_ptr 傳遞給函數,我想我更願意將 std::weak_ptr 作為參數,在該函數中進行檢查,而不是每次都在功能。 自然而然,您將獲得更少的代碼行。

否則,如果通常傳遞 std::shared_ptr,則函數內部自然不需要檢查,並且檢查 std:weak_ptr 在函數內部是否有效,將是開銷。

暫無
暫無

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

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