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




memory-management smart-pointers (8)

सरल सी ++ मॉडल

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

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

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

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

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

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

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

निष्कर्ष

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

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

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

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

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

तो सवाल:

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

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

सारांश:

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

std :: auto_ptr <टी>:

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

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

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

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

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

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

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

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

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

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

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


yasper :: ptr एक हल्का, बूस्ट :: shared_ptr विकल्प की तरह है। यह मेरे (अभी के लिए) छोटी परियोजना में अच्छी तरह से काम करता है।

http://yasper.sourceforge.net/ पर वेब पेज में निम्नानुसार वर्णित है:

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

* small (contained in single header)
* simple (nothing fancy in the code, easy to understand)
* maximum compatibility (drop in replacement for dumb pointers)

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


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

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


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


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

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


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


  • एक मालिक: कॉपी पर कॉपी उर्फ
  • std :: auto_ptr

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


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

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





ownership-semantics