खाली और अशक्त std :: shared_ptr के बीच C ++ में क्या अंतर है?


80

Cplusplus.com shared_ptrपेज एक के बीच एक अंतर से जुड़ी जानकारी खाली std::shared_ptr और एक अशक्त shared_ptrCppreference.com पेज स्पष्ट रूप से भेद बाहर फोन नहीं है, लेकिन का उपयोग करता है दोनों "खाली" और की तुलना nullptrकी, उसके वर्णन में std::shared_ptrव्यवहार।

क्या एक खाली और एक अशक्त के बीच अंतर है shared_ptr? क्या ऐसे मिश्रित-व्यवहार बिंदुओं के लिए कोई उपयोग मामला है? क्या एक गैर-रिक्त शून्य shared_ptrभी समझ में आता है? क्या कभी सामान्य उपयोग में कोई मामला होगा (यानी यदि आपने स्पष्ट रूप से एक निर्माण नहीं किया है) जहां आप एक खाली-लेकिन-गैर-नल के साथ समाप्त हो सकते हैं shared_ptr?

और अगर आप C ++ 11 संस्करण के बजाय Boost संस्करण का उपयोग कर रहे हैं, तो क्या इनमें से कोई उत्तर बदलता है?

जवाबों:


80

यह shared_ptrव्यवहार का एक अजीब कोना है । यह एक निर्माता आप एक बनाने के लिए अनुमति देता है कि है shared_ptrकि मालिक कुछ और करने के लिए अंक कुछ और:

template< class Y > 
shared_ptr( const shared_ptr<Y>& r, T *ptr );

shared_ptrइस निर्माता का प्रयोग कर बनाया शेयरों स्वामित्व के साथ rहै, लेकिन करने के लिए अंक जो कुछ भी ptrकरने के लिए अंक (यानी, कॉल get()या operator->()वापस आ जाएगी ptr)। यह उन मामलों के लिए आसान है जहां ptrस्वामित्व वाली वस्तु के एक सबोबिज (जैसे, एक डेटा सदस्य) को इंगित करता है r

पेज आप कॉल किसी लिंक किए गए shared_ptrकि कुछ भी नहीं मालिक खाली है, और एक shared_ptrहै कि कुछ भी नहीं करने के लिए अंक (यानी, जिसका get() == nullptr) अशक्त । ( मानक द्वारा इस अर्थ में खाली का उपयोग किया जाता है; शून्य नहीं है।) आप एक अशक्त-लेकिन-नहीं-रिक्त का निर्माण कर सकते हैं shared_ptr, लेकिन यह बहुत उपयोगी नहीं होगा। एक खाली-लेकिन-नहीं-शून्य shared_ptrअनिवार्य रूप से एक गैर-मालिक सूचक है, जिसका उपयोग कुछ अजीब चीजें करने के लिए किया जा सकता है जैसे कि एक सूचक को स्टैक पर आवंटित फ़ंक्शन को आवंटित करने की अपेक्षा एक फ़ंक्शन की उम्मीद हैshared_ptr (लेकिन मैं सुझाव दूंगा कि जो कोई भी shared_ptrअंदर डाल दे। एपीआई पहले)।

boost::shared_ptrइसके पास एक कंस्ट्रक्टर भी है , जिसे वे अलियासिंग कंस्ट्रक्टर कहते हैं


8
वर्थ नोटिंग: C ++ 11 .7 20.7.2.2.1 (p16) "नोट: यह कंस्ट्रक्टर shared_ptrएक गैर-पूर्ण संग्रहित पॉइंटर के साथ एक खाली उदाहरण के निर्माण की अनुमति देता है ।" पूर्ववर्ती नोट (p15) का उल्लेख करने के लायक भी, "झूलने वाले पॉइंटर की संभावना से बचने के लिए, इस निर्माता के उपयोगकर्ता को यह सुनिश्चित करना होगा कि pकम से कम तब तक वैध रहे जब तक कि स्वामित्व समूह rनष्ट न हो जाए।" एक शायद ही कभी इस्तेमाल किया निर्माण।
WhozCraig

@ कुब्बी ए shared_ptrजिसका get()रिटर्न nullptr किसीnullptr भी चीज़ के मालिक होने के बावजूद तुलना के बराबर है ।
टीसी

3
एक अशक्त लेकिन-गैर-खाली shared_ptrएस उपयोगी हो सकता है, यह सुनिश्चित करने के लिए कि कुछ फ़ंक्शन एक बार निष्पादित हो जाते हैं जब सभी मालिक बिंदु दायरे से बाहर चले जाते हैं (यहां तक ​​कि अपवाद के मामले में भी!)। यकीन नहीं होता, क्या अब इसके लिए कोई विशेष वर्ग है।
कोल्डफिक्स

@coldfix एक अशक्त-लेकिन-गैर-रिक्त क्या कर सकता shared_ptrहै जो एक गैर-अशक्त और गैर-रिक्त shared_ptrनहीं कर सकता है?
टीसी

2
अलियासिंग कंस्ट्रक्टर ब्लूमबर्ग से उत्पन्न होता है और इसे बूस्ट में लागू करने से पहले मानक के लिए प्रस्तावित किया गया था ( एन 1851 देखें )। मैं मानक शब्द "स्वामित्व के साथ" साझा करने के लिए r"इस वाक्यांश को" "जो कुछ भी rमालिक है" पसंद करता हूं
जोनाथन वेकली

9

क्या खाली और अशक्त शेयर्ड_एप्ट्र के बीच अंतर है?

खाली shared_ptrमें नियंत्रण खंड नहीं है और इसका उपयोग गणना माना जाता है 0. खाली की प्रतिलिपि shared_ptrएक और खाली है shared_ptr। वे दोनों अलग-अलग हैं जो shared_ptrसामान्य नियंत्रण ब्लॉक को साझा नहीं करते हैं क्योंकि उनके पास यह नहीं है। खाली shared_ptrका निर्माण डिफॉल्ट कंस्ट्रक्टर या कंस्ट्रक्टर के साथ किया जा सकता है nullptr

गैर-रिक्त नल shared_ptrमें नियंत्रण ब्लॉक होता है जिसे अन्य shared_ptrएस के साथ साझा किया जा सकता है । नॉन-खाली नल की कॉपी वह shared_ptrहै shared_ptrजो नियंत्रण ब्लॉक को मूल के रूप में साझा करता है shared_ptrइसलिए उपयोग की संख्या 0. नहीं है। यह कहा जा सकता है कि सभी प्रतियां shared_ptrसमान हैंnullptr । गैर-रिक्त नल shared_ptrका निर्माण ऑब्जेक्ट के प्रकार के शून्य सूचक के साथ किया जा सकता है (नहीं nullptr)

यहाँ उदाहरण है:

#include <iostream>
#include <memory>

int main()
{
    std::cout << "std::shared_ptr<int> ptr1:" << std::endl;
    {
        std::shared_ptr<int> ptr1;
        std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
        std::shared_ptr<int> ptr2 = ptr1;
        std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
        std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
    }
    std::cout << std::endl;

    std::cout << "std::shared_ptr<int> ptr1(nullptr):" << std::endl;
    {
        std::shared_ptr<int> ptr1(nullptr);
        std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
        std::shared_ptr<int> ptr2 = ptr1;
        std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
        std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
    }
    std::cout << std::endl;

    std::cout << "std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))" << std::endl;
    {
        std::shared_ptr<int> ptr1(static_cast<int*>(nullptr));
        std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
        std::shared_ptr<int> ptr2 = ptr1;
        std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
        std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
    }
    std::cout << std::endl;

    return 0;
}

यह आउटपुट:

std::shared_ptr<int> ptr1:
    use count before copying ptr: 0
    use count  after copying ptr: 0
    ptr1 is null

std::shared_ptr<int> ptr1(nullptr):
    use count before copying ptr: 0
    use count  after copying ptr: 0
    ptr1 is null

std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))
    use count before copying ptr: 1
    use count  after copying ptr: 2
    ptr1 is null

http://coliru.stacked-crooked.com/a/54f5973090905ed2ff


1
मुझे लगता है कि यह बेहतर जवाब है कि क्यों हमें share_ptr के कस्टम डीलेटर में नल की जांच करनी है। क्या यह share_ptr के कस्टम डिलेटर में nullptr के लिए जाँच करने के लिए समझ में आता है?
डेविड ली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.