उपयोग करने का लाभ std::unique_ptr<T>
(एक तरफ से कॉल करने के लिए delete
या delete[]
स्पष्ट रूप से याद नहीं रखने के लिए ) यह है कि यह गारंटी देता है कि एक सूचक nullptr
या तो (आधार) ऑब्जेक्ट के एक वैध उदाहरण को इंगित करता है। के बाद मैं आपके प्रश्न का उत्तर मैं यह करने के लिए वापस आ जाएगा, लेकिन पहले संदेश है डीओ स्मार्ट संकेत का उपयोग गतिशील रूप से आवंटित वस्तुओं के जीवन का प्रबंधन करने के।
अब, आपकी समस्या वास्तव में अपने पुराने कोड के साथ इसका उपयोग करना है ।
मेरा सुझाव यह है कि यदि आप स्वामित्व को स्थानांतरित या साझा नहीं करना चाहते हैं, तो आपको हमेशा ऑब्जेक्ट के संदर्भ में पास करना चाहिए । अपने कार्य को इस तरह घोषित करें ( const
आवश्यकतानुसार या बिना किसी क्वालिफायर के)
bool func(BaseClass& ref, int other_arg) { ... }
फिर कॉल करने वाला, जिसके पास std::shared_ptr<BaseClass> ptr
या तो nullptr
मामला होगा या वह bool func(...)
परिणाम की गणना करने के लिए कहेगा :
if (ptr) {
result = func(*ptr, some_int);
} else {
}
इसका मतलब है कि किसी भी कॉलर को यह वादा करना होगा कि संदर्भ वैध है और यह फ़ंक्शन निकाय के निष्पादन के दौरान मान्य रहेगा।
यही कारण है कि मैं दृढ़ता से मानता हूं कि आपको कच्चे पॉइंटर्स या स्मार्ट पॉइंटर्स के संदर्भों को पारित नहीं करना चाहिए ।
एक कच्चा सूचक केवल एक स्मृति पता है। एक (कम से कम) 4 अर्थ हो सकते हैं:
- मेमोरी के एक ब्लॉक का पता जहां आपकी इच्छित वस्तु स्थित है। ( अच्छा )
- पता 0x0 जो कि आप निश्चित हो सकते हैं, निंदनीय नहीं है और इसमें "कुछ भी नहीं" या "अन्य वस्तु" का शब्दार्थ हो सकता है। ( बुरा )
- स्मृति के एक ब्लॉक का पता जो आपकी प्रक्रिया के पता योग्य स्थान के बाहर है (यह आपके कार्यक्रम को दुर्घटनाग्रस्त होने का कारण होगा)। ( बदसूरत )
- मेमोरी के एक ब्लॉक का पता जिसे डिरेल किया जा सकता है लेकिन जिसमें वह नहीं है जिसकी आप अपेक्षा करते हैं। हो सकता है कि पॉइंटर को गलती से संशोधित किया गया था और अब यह एक और लिखने योग्य पते (आपकी प्रक्रिया के भीतर एक पूरी तरह से अन्य चर) की ओर इशारा करता है। इस मेमोरी लोकेशन पर लिखने से, निष्पादन के दौरान, कई बार बहुत मज़ा आएगा, क्योंकि जब तक आपको वहां लिखने की अनुमति नहीं होगी, तब तक ओएस शिकायत नहीं करेगा। ( Zoinks! )
सही ढंग से स्मार्ट पॉइंटर्स का उपयोग करने से डरावने मामलों की संख्या 3 और 4 कम हो जाती है, जो आमतौर पर संकलन के समय में पता लगाने योग्य नहीं होते हैं और जिन्हें आप आमतौर पर रनटाइम के दौरान अनुभव करते हैं जब आपका प्रोग्राम क्रैश हो जाता है या अप्रत्याशित चीजें करता है।
तर्क के रूप में स्मार्ट पॉइंटर्स को पास करने के दो नुकसान हैं: आप बिना कॉपी किए (जो ओवरहेड जोड़ता है और जिसके लिए संभव नहीं है ) बिना इंगित किए गए ऑब्जेक्ट की const
-ness को नहीं बदल सकते हैं , और आप अभी भी दूसरे ( ) अर्थ के साथ छोड़ दिए गए हैं ।shared_ptr
unique_ptr
nullptr
मैंने एक डिजाइन के नजरिए से दूसरे मामले को ( खराब ) के रूप में चिह्नित किया । यह जिम्मेदारी के बारे में अधिक सूक्ष्म तर्क है।
कल्पना करें कि जब कोई फ़ंक्शन nullptr
अपने पैरामीटर के रूप में प्राप्त करता है तो इसका क्या अर्थ है । यह पहले तय करना है कि इसके साथ क्या करना है: लापता वस्तु के स्थान पर "जादुई" मूल्य का उपयोग करें? व्यवहार को पूरी तरह से बदल दें और कुछ और गणना करें (जिसे ऑब्जेक्ट की आवश्यकता नहीं है)? घबराहट और एक अपवाद फेंक? इसके अलावा, तब क्या होता है जब फ़ंक्शन कच्चे सूचक द्वारा 2 या 3 या उससे अधिक तर्क लेता है? इसमें से प्रत्येक को जांचना होगा और उसके अनुसार अपने व्यवहार को अनुकूलित करना होगा। यह बिना किसी वास्तविक कारण के इनपुट सत्यापन के शीर्ष पर एक नया स्तर जोड़ता है।
इन निर्णयों को करने के लिए कॉल करने वाला पर्याप्त संदर्भ जानकारी वाला होना चाहिए, या, दूसरे शब्दों में, जितना आप जानते हैं उतना बुरा कम भयावह है। दूसरी ओर, फ़ंक्शन को बस कॉलर का वादा करना चाहिए कि जिस मेमोरी को इंगित किया गया है वह उद्देश्य के साथ काम करने के लिए सुरक्षित है। (संदर्भ अभी भी स्मृति पते हैं, लेकिन वैचारिक रूप से वैधता के एक वादे का प्रतिनिधित्व करते हैं।)
std::unique_ptr
एकstd::vector<std::unique_ptr>
तर्क के लिए छुटकारा दिलाता है?