有沒有辦法區分分配的(可能過期的)weak_ptr和未分配的weak_ptr。如何檢查weak_ptr是否爲空(未分配)?
weak_ptr<int> w1;
weak_ptr<int> w2 = ...;
我瞭解以下檢查是否爲非轉讓或過期,但是是否存在僅用於非轉讓的(便宜?)檢查?
if (!w.lock()) { /* either not assigned or expired */ }
有沒有辦法區分分配的(可能過期的)weak_ptr和未分配的weak_ptr。如何檢查weak_ptr是否爲空(未分配)?
weak_ptr<int> w1;
weak_ptr<int> w2 = ...;
我瞭解以下檢查是否爲非轉讓或過期,但是是否存在僅用於非轉讓的(便宜?)檢查?
if (!w.lock()) { /* either not assigned or expired */ }
您可以使用兩種調用owner_before
檢查與構建一個默認的平等(空)弱指針:
template <typename T>
bool is_uninitialized(std::weak_ptr<T> const& weak) {
using wt = std::weak_ptr<T>;
return !weak.owner_before(wt{}) && !wt{}.owner_before(weak);
}
這隻會返回true
如果w{} "==" weak
,其中"=="
比較所有者,並根據en.cppreference.com:
的順序是這樣的,兩個智能指針比較只相當於如果它們都是空的,或者如果他們都擁有相同的對象,即使get()獲得的指針的值不同(例如,因爲它們指向同一對象內的不同子對象)。
由於默認構造函數構造空弱指針,這隻能返回true
如果weak
也空。這將不返回true
如果weak
已過期。
看着生成的彙編(最優化),這似乎是相當優化:
bool is_uninitialized<int>(std::weak_ptr<int> const&):
cmp QWORD PTR [rdi+8], 0
sete al
ret
...相比,檢查weak.expired()
:
bool check_expired(std::weak_ptr<int> const&):
mov rdx, QWORD PTR [rdi+8]
mov eax, 1
test rdx, rdx
je .L41
mov eax, DWORD PTR [rdx+8]
test eax, eax
sete al
.L41:
rep ret
...或returning !weak.lock()
(〜80線的組裝)。
使用的std :: weak_ptr的::過期()
#include <iostream>
#include <memory>
//declare a weak pointer
std::weak_ptr<int> gw;
void f()
{
//check if expired
if (!gw.expired()) {
std::cout << "pointer is valid\n";
}
else {
std::cout << "pointer is expired\n";
}
}
int main()
{
f();
{
auto cre = std::make_shared<int>(89);
gw = cre;
f();
}
f();
}
輸出
pointer is expired
pointer is valid
pointer is expired
Program ended with exit code: 0
'stl :: expired'不是問題。你的意思是['std :: weak_ptr
我的看法是,這比在分配對象的情況下檢查nullptr要慢。 – Zuza
你可以嘗試創建一個共享的指針,它接受一個弱指針作爲參數,並提出了一個std::bad_weak_ptr異常,如果一個弱指針已過期(或在您的情況下未分配的):
#include <memory>
#include <iostream>
int main(){
// with an assigned pointer
std::shared_ptr<int> p1(new int(42));
std::weak_ptr<int> w1(p1);
try {
std::shared_ptr<int> p2(w1);
}
catch (const std::bad_weak_ptr& e) {
std::cout << e.what() << '\n';
}
// with a non assigned pointer
std::shared_ptr<int> p2(new int(42));
std::weak_ptr<int> w2;
try {
std::shared_ptr<int> p2(w2); // raises an exception
}
catch (const std::bad_weak_ptr& e) {
std::cout << "Ptr 2: " << e.what() << '\n';
}
}
這確實解決了我的問題,但在簡單檢查的預期路徑中引發異常似乎很糟糕。 – Zuza
您可以使用'過期',但AFAIK沒有辦法區分。 – NathanOliver
模擬['std :: optional'](http://en.cppreference.com/w/cpp/utility/optional)的東西可能是 – AndyG