[英]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.