2017-08-04 3 views
8

क्या एक असाइन किए गए (संभवतः समाप्त हो चुके) weak_ptr और एक गैर-निर्दिष्ट एक के बीच अंतर करने का कोई तरीका है।कैसे जांचें कि weak_ptr खाली है (गैर-निर्दिष्ट)?

weak_ptr<int> w1; 
weak_ptr<int> w2 = ...; 

मैं या तो गैर काम या समाप्ति के लिए निम्नलिखित जांच समझते हैं, लेकिन वहाँ है एक (सस्ता?) केवल गैर-कार्य के लिए जाँच?

if (!w.lock()) { /* either not assigned or expired */ } 
+0

आप उपयोग कर सकते हैं 'समाप्त हो गया' लेकिन AFAIK में अंतर बताने का कोई तरीका नहीं है। – NathanOliver

+0

कुछ जो अनुकरण करता है ['std :: वैकल्पिक'] (http://en.cppreference.com/w/cpp/utility/optional) शायद – AndyG

उत्तर

12

आप (एक डिफ़ॉल्ट का निर्माण के साथ समानता खाली जाँच करने के लिए 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 के अनुसार:

क्रम ऐसा है कि दो स्मार्ट संकेत बराबर ही अगर वे दोनों खाली हैं तुलना या अगर वे दोनों एक ही मालिक हैं वस्तु, भले ही प्राप्त() द्वारा प्राप्त पॉइंटर्स के मान अलग हैं (उदाहरण के लिए क्योंकि वे एक ही वस्तु के भीतर विभिन्न subobjects पर इंगित करते हैं)।

क्योंकि डिफ़ॉल्ट निर्माता एक खाली कमजोर सूचक निर्माण करती है, यह केवल लौट सकते हैं true अगर weak भी खाली है। trueweak की समयसीमा समाप्त हो जाएगी।

उत्पन्न विधानसभा (अनुकूलन के साथ) को देखते हुए, यह बहुत अनुकूलित लगता है:

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 लाइनों असेंबली के)।

+0

बहुत बढ़िया समाधान + सत्यापन। – Zuza

+0

वास्तव में अच्छा जवाब है। एक सुंदर अस्पष्ट चाल है, लेकिन यह कम से कम काम कर सकता है। +1 – skypjack

0

का उपयोग 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 
+0

' stl :: कालबाह्य 'कोई बात नहीं है। आपका मतलब है ['std :: weak_ptr :: कालबाह्य()'] (http://en.cppreference.com/w/cpp/memory/weak_ptr/expired)। –

+0

मेरा विश्वास यह है कि वस्तु को असाइन किए जाने की स्थिति में नलप्टर की जांच करने से धीमा है। – Zuza

0

आप एक साझा सूचक है कि एक पैरामीटर के रूप में एक कमजोर सूचक स्वीकार करता है और एक 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'; 
    } 
} 
+1

यह मेरी समस्या का समाधान करता है, लेकिन एक साधारण चेक के अपेक्षित पथ में अपवाद उठाना बुरा लगता है। – Zuza

संबंधित मुद्दे