2008-11-17 7 views
39

क्या आपको वही पॉइंटर हटा देना है जो नए द्वारा लौटाया गया था, या क्या आप कक्षाओं के आधार प्रकारों में से किसी एक को पॉइंटर पास कर सकते हैं? उदाहरण के लिए:आधार वर्ग के लिए पॉइंटर्स के साथ काम हटा देता है?

class Base 
{ 
public: 
    virtual ~Base(); 
    ... 
}; 

class IFoo 
{ 
public: 
    virtual ~IFoo() {} 
    virtual void DoSomething() = 0; 
}; 

class Bar : public Base, public IFoo 
{ 
public: 
    virtual ~Bar(); 
    void DoSomething(); 
    ... 
}; 

Bar * pBar = new Bar; 
IFoo * pFoo = pBar; 
delete pFoo; 

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

क्या यह संभवतः काम कर सकता है? मेरा अंतर्ज्ञान नहीं कहता है, क्योंकि पॉइंटर्स के पास एक ही पता नहीं होगा। दूसरी तरफ, एक गतिशील_कास्ट < बार *> काम करना चाहिए, इसलिए कहीं भी संकलक इसे समझने के लिए पर्याप्त जानकारी संग्रहीत कर रहा है।


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

mov eax, DWORD PTR _this$[ebp] 

कोडांतरक ट्रेसिंग से पता चला है कि इस सूचक हटाने कार्य करने के लिए पारित किया जा रहा था। रहस्य सुलझ गया।

मैंने आभासी विनाशक को IFoo में जोड़ने के लिए उदाहरण तय कर दिया है, यह एक साधारण निरीक्षण थी। उन सभी को धन्यवाद जिन्होंने इसे इंगित किया।

उत्तर

52

हाँ, यह काम करेंगे, यदि और केवल यदि आधार वर्ग नाशक, आभासी है जो आप Base आधार वर्ग के लिए किया है लेकिन IFoo आधार वर्ग के लिए नहीं। यदि बेस क्लास विनाशक वर्चुअल है, तो जब आप बेस क्लास पॉइंटर पर operator delete पर कॉल करते हैं, तो यह आभासी फ़ंक्शन तालिका में व्युत्पन्न क्लास विनाशक को देखकर ऑब्जेक्ट को हटाने का तरीका जानने के लिए गतिशील प्रेषण का उपयोग करता है।

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

+0

मुझे ऑब्जेक्ट को सही तरीके से नष्ट करने के लिए आभासी विनाशक के महत्व को पता है, इसलिए मैंने इसे उदाहरण में शामिल किया है; आप कह रहे हैं कि इससे उचित स्मृति मुक्त हो जाएगी? और मुझे इफू के लिए आभासी विनाशक भी चाहिए? –

+0

असल में किसी भी संदर्भ को हटाने के लिए ठीक है जब तक कि अधिकांश वर्ग में वर्चुअल विनाशक होता है। एक बार विनाशक आभासी होने के बाद, सभी व्युत्पन्न कार्यान्वयन में एक आभासी विनाशक होगा चाहे वह निर्दिष्ट है या नहीं। सी ++ मजेदार है। – JaredPar

+3

वर्चुअल विनाशक के बिना भी वास्तविक स्मृति को मुक्त किया जाएगा। – Eclipse

3

यह आपके दिए गए उदाहरण से संबंधित नहीं है, लेकिन चूंकि आपने उल्लेख किया है कि आप shared_ptr के स्वामित्व वाले ऑब्जेक्ट को हटाते समय वास्तव में रुचि रखते हैं, तो आप shared_ptr के 'डिलीटर' का उपयोग करने में रुचि रखते हैं।

यदि shared_ptr के स्वामित्व वाले ऑब्जेक्ट को हटाए जाने पर विशेष हैंडलिंग की आवश्यकता है, तो आप किसी विशेष shared_ptr<> के लिए 'डिलीटर' निर्दिष्ट कर सकते हैं। डिलीटर इस प्रकार का हिस्सा नहीं है, यह shared_ptr<> उदाहरण की विशेषता है, इसलिए shared_ptr<> ऑब्जेक्ट्स के आपके कंटेनर में अलग-अलग डिलीटर वाले कुछ ऑब्जेक्ट्स हो सकते हैं।यहाँ बूस्ट डॉक्स shared_ptr<> Deleter के बारे में क्या कहना है:

कस्टम deallocators एक shared_ptr की ओर लौटने एक कारखाने समारोह अपनी स्मृति आवंटन रणनीति से उपयोगकर्ता बचाने अनुमति देते हैं। चूंकि डेलोकेटर प्रकार का हिस्सा नहीं है, आवंटन रणनीति को बदलकर ब्रेक स्रोत या बाइनरी संगतता नहीं है, और क्लाइंट रीकंपिलेशन की आवश्यकता नहीं है। उदाहरण के लिए, एक "नहीं-op" deallocator उपयोगी जब एक स्थिर आवंटित ऑब्जेक्ट में एक shared_ptr लौटने, और अन्य रूपों एक shared_ptr एक और स्मार्ट सूचक के लिए एक आवरण के रूप में प्रयोग की जाने वाली, अंतर को कम अनुमति देते हैं।

यह साफ हो अगर आप एक आभासी नाशक के बाद से आप वस्तुओं है कि एक IFoo संदर्भ या सूचक के माध्यम से इसके बारे में उपवर्गों हैं नष्ट करने के लिए योजना बना रहे हैं के लिए IFoo संशोधित कर सकते हैं। लेकिन अगर आप IFoo से फंस गए हैं जिसे सही नहीं किया जा सकता है, तो यदि आप अपने कंटेनर में shared_ptr<IFoo> का उपयोग करना चाहते हैं, लेकिन इसे Bar पर इंगित करना है, तो आप shared_ptr इंस्टेंस को एक डिलीटर के साथ बना सकते हैं जो Bar* पर डाउनकास्ट करता है हटाना ऑपरेशन करता है। डाउनकास्ट को खराब रूप माना जाता है, लेकिन यह तकनीक ऐसी चीज हो सकती है जिसे आप बाध्य में उपयोग कर सकते हैं।

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