[英]What is diffrence between lock() and expired()? weak_ptr C++
最近我開始使用 C++11。 我研究了weak_ptr
。 有兩種獲取原始指針的方法。
lock()
函數
shared_ptr<Foo> spFoo = wpPtr.lock(); if(spFoo) { spFoo->DoSomething(); }
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();
這使得代碼在沒有縮進、條件或跳轉的情況下以扁平線“預期”執行。
第二種變體有兩個問題:
wpPtr.expired()
spFoo
之前缺少必要的檢查if (spFoo)
第一個變體是事務性的,當您最終需要使用弱指針引用的對象時,可以使用該變體。
下面是一個weak_ptr
的相關操作。 您應該選擇選項 1,因為方法 2 不是線程安全的。
w.use_count()
與w
共享所有權的shared_ptr
的數量如果
w.use_count()
為零,則w.expired()
返回true
,否則返回false
w.lock()
如果expired
為true
,則返回一個 nullshared_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
}
選項 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.