簡體   English   中英

lock() 和 expired() 有什么區別? weak_ptr C++

[英]What is diffrence between lock() and expired()? weak_ptr C++

最近我開始使用 C++11。 我研究了weak_ptr 有兩種獲取原始指針的方法。

  1. lock()函數

    shared_ptr<Foo> spFoo = wpPtr.lock(); if(spFoo) { spFoo->DoSomething(); }
  2. expired()函數

    if(!wpPtr.expired()) { shared_ptr<Foo> spFoo = wpPtr.lock(); spFoo->DoSomething(); }

哪種方法更好? 這兩種方式有什么不同?

所以共享 ptr 和弱 ptr 是線程安全的,因為如果你有一個給定線程本地對象的實例,並且它們共享一個公共指向對象,你可以在一個線程和另一個線程中與它們交互,一切正常。

為了使其正常工作,您必須正確使用它們。

wp.expired()僅用於執行諸如“從緩沖區中刪除每個過期的弱 ptr”之類的操作。 它對您提出的目的沒有用。

每個弱指針一旦過期,就會保持過期狀態。 但是,在您確認已使用后,已使用的弱指針可能會立即過期。

if(!wpPtr.expired())  {
  // <<--- here
  shared_ptr<Foo> spFoo = wpPtr.lock();
  spFoo->DoSomething();
}

<<--- here ,我們一無所知的狀態wpPtr在多線程環境。 它可能已過期或未過期。 另一方面:

if(wpPtr.expired())  {
  // <<--- there
}

<<--- there我們確實知道弱指針已過期。

與文件 io 和其他類型的“事務性”操作一樣,檢查您是否可以做某事的唯一方法就是嘗試去做 在確定您應該能夠做到和做到這一點之間,狀態可能會改變並且操作可能會失敗。

有時你會發現你幾乎肯定不能早點,這有時很有用,但你不能確定你能做到,直到你嘗試。 嘗試嘗試可能會失敗,此時您將處理錯誤。

if(auto spFoo = wpPtr.lock())  {
  spFoo->DoSomething();
}

這是與弱指針交互的“正確”方式。 測試弱指針的有效性,並在同一操作中獲取共享指針。

if()標頭之外創建spFoo是可以接受的,我更喜歡這種技術,因為spFoo的范圍完全限於它有效的區域。

另一種首選技術是提前退出:

auto spFoo = wpPtr.lock();

if(!spFoo) return error("wp empty");

spFoo->DoSomething();

這使得代碼在沒有縮進、條件或跳轉的情況下以扁平線“預期”執行。

第二種變體有兩個問題:

  1. 它做了一個不必要的檢查wpPtr.expired()
  2. 在取消引用spFoo之前缺少必要的檢查if (spFoo)

第一個變體是事務性的,當您最終需要使用弱指針引用的對象時,可以使用該變體。

下面是一個weak_ptr的相關操作。 您應該選擇選項 1,因為方法 2 不是線程安全的。

w.use_count()w共享所有權的shared_ptr的數量

如果w.use_count()為零,則w.expired()返回true ,否則返回false

w.lock()如果expiredtrue ,則返回一個 null shared_ptr 否則返回一個shared_ptrw指向的對象。

(2) 不是線程安全的

// let p be the last shared_ptr pointing at the same object as wpPtr
if (!wpPtr.expired())
{
    // we enter the if-statement because wpPtr.use_count() is 1
    // p goes out of scope on its thread, the object gets deleted
    shared_ptr<Foo> spFoo = wpPtr.lock(); // null shared_ptr
    spFoo->DoSomething(); // ERROR! deferencing null pointer
}

(1) 線程安全

// let p be the last shared_ptr pointing at the same object as wpPtr
shared_ptr<Foo> spFoo = wpPtr.lock();
// now, wpPtr.use_count() is 2, because spFoo and p are both pointing at the object
// p goes out of scope on its thread, but spFoo is still pointing at the object
if(spFoo) {
    spFoo->DoSomething(); // OK! safe to dereference
}

選項 1

如果您使用選項 2,那么在調用wpPtr.expired()和調用wpPtr.lock()weak_ptr可能已經過期,並且行spFoo->DoSomething()將嘗試取消引用 null shared_ptr

cppreference.com引用:

std::weak::lock有效返回

expired() ? shared_ptr<T>() : shared_ptr<T>(*this)

使用 expired 檢查底層對象是否有效並鎖定以潛在地將對象提升為std::shared_ptr

暫無
暫無

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

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