c++ स्मार्ट प्वाइंटर्स: या आप बच्चे का मालिक कौन है?




memory-management smart-pointers (9)

बूस्ट से, पॉइंटर कंटेनर लाइब्रेरी भी है। स्मार्ट पॉइंटर्स के मानक कंटेनर की तुलना में ये थोड़ा अधिक कुशल और उपयोग करने में आसान हैं, यदि आप केवल अपने कंटेनर के संदर्भ में ऑब्जेक्ट्स का उपयोग करेंगे।

विंडोज़ पर, COM पॉइंटर्स (IU अज्ञात, IDISpatch, और दोस्तों), और उन्हें संभालने के लिए विभिन्न स्मार्ट पॉइंटर्स हैं (उदाहरण के लिए एटीएल के CComPtr और स्मार्ट पॉइंटर्स जो _com_ptr क्लास के आधार पर विजुअल स्टूडियो में "आयात" कथन द्वारा स्वतः उत्पन्न _com_ptr )।

सी ++ स्मृति स्वामित्व के बारे में सब कुछ है
उर्फ " स्वामित्व सेमेन्टिक्स "

यह स्मृति जारी करने के लिए गतिशील आवंटित स्मृति के एक हिस्से के मालिक की ज़िम्मेदारी है। तो सवाल वास्तव में बन जाता है जो स्मृति का मालिक है।

सी ++ स्वामित्व में इस तरह से दस्तावेज किया जाता है कि एक रॉ पॉइंटर को अच्छे (आईएमओ) सी ++ प्रोग्राम में लपेटा जाता है, यह बहुत दुर्लभ है [आरएआरई पॉइंटर्स को पास नहीं किया गया है) के रूप में आरएडब्लू पॉइंटर्स के पास कोई अनुमानित स्वामित्व नहीं है, इसलिए हम नहीं कर सकते बताएं कि स्मृति का मालिक कौन है और इस प्रकार दस्तावेज़ीकरण को सावधानीपूर्वक पढ़ने के बिना आप यह नहीं बता सकते कि स्वामित्व के लिए कौन जिम्मेदार है)।

इसके विपरीत, एक वर्ग में संग्रहीत रॉ पॉइंटर्स को देखना दुर्लभ है, प्रत्येक रॉ पॉइंटर को अपने स्मार्ट पॉइंटर रैपर में संग्रहीत किया जाता है। ( एनबी: यदि आपके पास किसी ऑब्जेक्ट का स्वामित्व नहीं है तो आपको इसे संग्रहीत नहीं किया जाना चाहिए क्योंकि आप नहीं जानते कि यह कब गुंजाइश से बाहर हो जाएगा और नष्ट हो जाएगा।)

तो सवाल:

  • किस प्रकार की स्वामित्व सेमेन्टिक लोग आते हैं?
  • उन अर्थशास्त्रों को लागू करने के लिए मानक कक्षाओं का उपयोग किया जाता है?
  • आप उन्हें किस स्थिति में उपयोगी पाते हैं?

आइए प्रति जवाब 1 प्रकार का अर्थपूर्ण स्वामित्व रखें ताकि उन्हें व्यक्तिगत रूप से ऊपर और नीचे वोट दिया जा सके

सारांश:

संकल्पनात्मक स्मार्ट पॉइंटर्स सरल हैं और एक निष्पक्ष कार्यान्वयन आसान है। मैंने कई प्रयासों को कार्यान्वित किया है, लेकिन अनिवार्य रूप से वे किसी भी तरह से टूटे हुए हैं जो आकस्मिक उपयोग और उदाहरणों के लिए स्पष्ट नहीं है। इस प्रकार मैं हमेशा अपनी खुद की रोलिंग के बजाए लाइब्रेरी से अच्छी तरह से परीक्षण किए गए "स्मार्ट प्वाइंटर्स" का उपयोग करने की सलाह देता हूं। std :: auto_ptr या बूस्ट स्मार्ट पॉइंटर्स में से एक मेरी सभी ज़रूरतों को पूरा करने लगता है।

std :: auto_ptr <टी>:

एकल व्यक्ति वस्तु का मालिक है।
लेकिन स्वामित्व के हस्तांतरण की अनुमति है।

उपयोग:
======
यह आपको इंटरफेस को परिभाषित करने की अनुमति देता है जो स्वामित्व के स्पष्ट हस्तांतरण को दिखाता है।

को बढ़ावा देने :: scoped_ptr <टी>

एकल व्यक्ति वस्तु का मालिक है।
स्वामित्व का हस्तांतरण की अनुमति नहीं है।

उपयोग:
======
स्पष्ट स्वामित्व दिखाने के लिए प्रयुक्त।
ऑब्जेक्ट विनाशक द्वारा नष्ट किया जाएगा या जब स्पष्ट रूप से रीसेट हो जाएगा।

बढ़ावा :: shared_ptr <टी> (std :: tr1 :: shared_ptr <टी>)

एकाधिक स्वामित्व।
यह एक साधारण संदर्भ गिनती सूचक है। जब संदर्भ गणना शून्य वस्तु तक पहुंच जाती है तो नष्ट हो जाती है।

उपयोग:
======
जब ऑब्जेक्ट में जीवन भर के साथ कई ओवर हो सकते हैं जिन्हें संकलित समय पर निर्धारित नहीं किया जा सकता है।

को बढ़ावा देने :: weak_ptr <टी>

Shared_ptr <T> के साथ प्रयुक्त।
ऐसी परिस्थितियों में जहां पॉइंटर्स का चक्र हो सकता है।

उपयोग:
======
चक्रों को बनाए रखने से चक्रों को रोकने के लिए प्रयुक्त होता है जब चक्र केवल साझा रेफकाउंट बनाए रखता है।


स्वामित्व साझा नहीं किया है। यदि आप करते हैं, तो सुनिश्चित करें कि यह केवल उस कोड के साथ है जिसे आप नियंत्रित नहीं करते हैं।

इससे 100% समस्याएं हल होती हैं, क्योंकि यह आपको यह समझने के लिए मजबूर करती है कि सब कुछ कैसे इंटरैक्ट करता है।


सरल सी ++ मॉडल

अधिकांश मॉड्यूल में मैंने देखा, डिफ़ॉल्ट रूप से, यह माना गया था कि पॉइंटर्स प्राप्त करना स्वामित्व प्राप्त नहीं कर रहा था। वास्तव में, एक सूचक के स्वामित्व को त्यागने वाले कार्यों / विधियों दोनों बहुत ही दुर्लभ थे और स्पष्ट रूप से उनके दस्तावेज़ीकरण में तथ्य व्यक्त करते थे।

यह मॉडल मानता है कि उपयोगकर्ता केवल वही है जो वह स्पष्ट रूप से आवंटित करता है । बाकी सब कुछ स्वचालित रूप से (दायरे से बाहर निकलने पर, या आरएआईआई के माध्यम से) का निपटारा किया जाता है। यह एक सी-जैसा मॉडल है, जो इस तथ्य से बढ़ाया जाता है कि अधिकांश पॉइंटर्स ऑब्जेक्ट्स के स्वामित्व में होते हैं जो उन्हें स्वचालित रूप से हटाएंगे या जब आवश्यक हो (ऑब्जेक्ट्स पर विनाश, अधिकतर), और यह कि वस्तुओं की जीवन अवधि अनुमानित है (आरएआईआई आपका मित्र है, फिर)।

इस मॉडल में, कच्चे पॉइंटर्स स्वतंत्र रूप से परिचालित होते हैं और अधिकतर खतरनाक नहीं होते हैं (लेकिन यदि डेवलपर पर्याप्त स्मार्ट है, तो जब भी संभव हो, वह संदर्भों का उपयोग करेगा)।

  • कच्चे पॉइंटर्स
  • std :: auto_ptr
  • को बढ़ावा देने :: scoped_ptr

स्मार्ट पॉइंट सी ++ मॉडल

स्मार्ट पॉइंटर्स से भरे कोड में, उपयोगकर्ता ऑब्जेक्ट्स के जीवनकाल को अनदेखा करने की उम्मीद कर सकता है। मालिक कभी भी उपयोगकर्ता कोड नहीं होता है: यह स्मार्ट पॉइंटर स्वयं (आरएआईआई, फिर से) है। समस्या यह है कि संदर्भित स्मार्ट पॉइंटर्स के साथ मिश्रित परिपत्र संदर्भ घातक हो सकते हैं , इसलिए आपको साझा पॉइंटर्स और कमजोर पॉइंटर्स दोनों के साथ सौदा करना होगा। तो आपके पास अभी भी विचार करने के लिए स्वामित्व है (कमजोर पॉइंटर कुछ भी इंगित नहीं कर सकता है, भले ही कच्चे सूचक पर इसका लाभ यह है कि यह आपको बता सकता है)।

  • को बढ़ावा देने :: shared_ptr
  • को बढ़ावा देने :: weak_ptr

निष्कर्ष

कोई फर्क नहीं पड़ता कि मैं मॉडल का वर्णन करता हूं, अपवाद तक, एक पॉइंटर प्राप्त करने के लिए अपना स्वामित्व प्राप्त नहीं होता है और यह जानना अभी भी बहुत महत्वपूर्ण है कि कौन है । यहां तक ​​कि संदर्भों और / या स्मार्ट पॉइंटर्स का उपयोग करके सी ++ कोड का भारी उपयोग भी किया जाता है।


एकल-हस्तांतरणीय-मालिक का एक और बार उपयोग किया जाने वाला रूप है, और यह auto_ptr लिए बेहतर है क्योंकि यह auto_ptr के असाइनमेंट auto_ptr के पागल भ्रष्टाचार के कारण होने वाली समस्याओं से बचाता है।

मैं swap अलावा किसी और के बारे में बात नहीं करता। एक उपयुक्त swap फ़ंक्शन वाले किसी भी प्रकार को कुछ सामग्री के स्मार्ट संदर्भ के रूप में माना जा सकता है, जिसका स्वामित्व उसी समय के दूसरे उदाहरण में स्थानांतरित हो जाता है, जैसे उन्हें स्वामित्व में। प्रत्येक उदाहरण अपनी पहचान बरकरार रखता है लेकिन नई सामग्री के लिए बाध्य हो जाता है। यह एक सुरक्षित रूप से पुनर्निर्मित संदर्भ की तरह है।

(यह एक स्मार्ट सूचक के बजाय एक स्मार्ट संदर्भ है क्योंकि आपको सामग्री पर पहुंचने के लिए इसे स्पष्ट रूप से अस्वीकार करने की आवश्यकता नहीं है।)

इसका मतलब है कि auto_ptr कम आवश्यक हो जाता है - केवल उन अंतरों को भरने की आवश्यकता होती है जहां प्रकारों में अच्छा swap फ़ंक्शन नहीं होता है। लेकिन सभी std कंटेनर करते हैं।


  • साझा स्वामित्व
  • को बढ़ावा देने :: shared_ptr

जब एक संसाधन एकाधिक वस्तुओं के बीच साझा किया जाता है। बूस्ट shared_ptr यह सुनिश्चित करने के लिए संदर्भ गिनती का उपयोग करता है कि संसाधन को डी-आवंटित किया जाता है जब सभी को फिनिश किया जाता है।


  • एक मालिक
  • को बढ़ावा देने :: scoped_ptr

जब आपको गतिशील रूप से स्मृति आवंटित करने की आवश्यकता होती है लेकिन यह सुनिश्चित करना चाहते हैं कि यह ब्लॉक के प्रत्येक निकास बिंदु पर हटा दिया जाए।

मुझे यह उपयोगी लगता है क्योंकि इसे आसानी से संशोधित किया जा सकता है, और किसी रिसाव के बारे में चिंता किए बिना जारी किया जा सकता है


मेरे लिए, इन 3 प्रकारों में मेरी अधिकांश ज़रूरतें शामिल हैं:

shared_ptr - संदर्भ-गिनती, जब काउंटर शून्य तक पहुंच जाता है तो डेलोकेशन

weak_ptr - उपर्युक्त जैसा ही है, लेकिन यह एक shared_ptr लिए 'गुलाम' है, जिसे रद्द नहीं किया जा सकता है

auto_ptr - जब सृजन और विलोपन उसी कार्य के अंदर होता है, या जब ऑब्जेक्ट को केवल एक-स्वामी के रूप में माना जाना चाहिए। जब आप एक पॉइंटर को दूसरे को असाइन करते हैं, तो दूसरा ऑब्जेक्ट पहले से चुराता है।

मेरे पास मेरा अपना कार्यान्वयन है, लेकिन वे Boost में भी उपलब्ध हैं।

मैं अभी भी संदर्भ (ऑब्जेक्ट जब भी संभव हो) द्वारा ऑब्जेक्ट पास करता हूं, इस मामले में कॉल विधि को यह मानना ​​चाहिए कि ऑब्जेक्ट केवल कॉल के समय जीवित है।

एक और प्रकार का सूचक है जिसका मैं उपयोग करता हूं जिसे मैं hub_ptr कहता हूं । यह तब होता है जब आपके पास कोई ऑब्जेक्ट होता है जो उसमें घिरे ऑब्जेक्ट्स (आमतौर पर वर्चुअल बेस क्लास के रूप में) से सुलभ होना चाहिए। इसे weak_ptr पास करके हल किया जा सकता है, लेकिन इसमें खुद के लिए shared_ptr नहीं है। जैसा कि यह जानता है कि ये वस्तुएं उससे अधिक नहीं रहेंगी, यह उनके लिए एक hub_ptr गुजरती है (यह एक नियमित सूचक के लिए सिर्फ एक टेम्पलेट आवरण है)।


मुझे नहीं लगता कि मैं कभी भी अपने डिजाइन में स्वामित्व साझा करने की स्थिति में था। असल में, मेरे सिर के शीर्ष से एकमात्र वैध मामला मैं सोच सकता हूं कि फ्लाईवेट पैटर्न है।


std::tr1::shared_ptr<Blah> अक्सर आपकी सबसे अच्छी शर्त है।





ownership-semantics