2016-06-07 728 views
4

最近我從C++ 11開始。 我研究了約weak_ptr。有兩種獲取原始指針的方法。lock()和expired()之間有什麼區別? weak_ptr C++

  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(); 
    } 
    

哪個是更好的辦法?兩種方式有什麼不同?

回答

6

所以共享的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的範圍僅限於其有效的區域。

的其他優選技術是早早出局,在那裏你寫你的代碼SFINAE友好:

auto spFoo = wpPtr.lock(); 

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

spFoo->DoSomething(); 

這使得在一條直線的代碼流的「期望」執行無壓痕或條件或跳躍。

0

要從cppreference.com引述如下:

std::weak::lock有效返回

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

使用過期查詢的基礎對象是否有效,並鎖定到潛在促進對象到std::shared_ptr

+0

你放棄了報價的重要組成部分。這使得你的報價如此虛假我去檢查,看看如何解決cppreference。原來,這只是你的報價是錯誤的。 – Yakk

2

選項1

如果你去與選項2然後調用wpPtr.expired(),並呼籲wpPtr.lock()weak_ptr可能已經過期,該行spFoo->DoSomething()將嘗試取消引用空shared_ptr之間。

5

第二變型具有兩個問題:

  1. 它確實的不必要的檢查wpPtr.expired()
  2. 它缺少的必要檢查if (spFoo)解除引用spFoo

的第一變型是事務之前,和是當你最終需要使用弱指針引用的對象時使用的那個。

0

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

w.use_count()shared_ptr s表示股權與w

w.expired()返回true如果w.use_count()是零的數目,否則false

w.lock()如果expiredtrue,返回空shared_ptr;否則將shared_ptr返回到w指向的對象。

(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 
} 
相關問題