2009-02-24 15 views
12

मेरे पास पॉलिमॉर्फिक ऑब्जेक्ट्स का संग्रह है, जो सभी मेरे एनिमल क्लास: बिल्ली, कुत्ते और बंदरफिश से व्युत्पन्न हैं।मुझे पॉइंटर्स के वेक्टर की बजाय ऑब्जेक्ट्स के वेक्टर का उपयोग कब करना चाहिए?

मेरे आपरेशन के सामान्य मोड इसलिए की तरह, पशु संकेत का एक वेक्टर में इन वस्तुओं की दुकान के लिए है:

std :: वेक्टर < पशु *> my_vector;

 
my_vector.push_back(new Animal_Cat()); 
my_vector.push_back(new Animal_Dog()); 
my_vector.push_back(new Animal_MonkeyFish()); 

और जीवन बहुत अच्छा है ... या है ना?

मुझे हाल ही में बताया गया है कि मुझे वास्तव में इस फैशन में स्मृति आवंटित करने से बचने की कोशिश करनी चाहिए, क्योंकि यह स्मृति प्रबंधन को एक गड़बड़ी बनाता है। जब मुझे my_vector को नष्ट करने की आवश्यकता होती है, तो मुझे सभी तत्वों के माध्यम से पुन: प्रयास करना पड़ता है और सबकुछ हटा देता है।

मुझे नहीं लगता कि मैं संदर्भों का एक वेक्टर स्टोर कर सकता हूं (मैं इसके बारे में गलत हो सकता हूं), ऐसा लगता है कि पशु वस्तुओं के वेक्टर को स्टोर करना मेरा एकमात्र विकल्प है।

मुझे ऑब्जेक्ट्स के वेक्टर बनाम पॉइंटर्स के वेक्टर का उपयोग कब करना चाहिए? सामान्य रूप से, कौन सी विधि बेहतर है? (मैं ऑब्जेक्ट प्रतिलिपि जितना संभव हो उतना प्रतिलिपि बनाना चाहता हूं।)

उत्तर

17

जब भी संभव हो, आपको वस्तुओं के वेक्टर का उपयोग करना चाहिए; but in your case it isn't possible

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

मुख्य समाधान एक स्मार्ट सूचक का उपयोग करना है। प्री-सी ++ 11 auto_ptr, but that cannot be used in a standard container के साथ आता है। सी ++ 11 में std::unique_ptr और std::shared_ptr हैं जो कंटेनरों में उपयोग करने योग्य बनाने के लिए डिज़ाइन किए गए हैं (मुझे std::unique_ptr पसंद नहीं है जब तक कि मुझे वास्तव में संदर्भ गणना की आवश्यकता न हो)। यदि आप सी ++ 11 का उपयोग नहीं कर सकते हैं, तो सबसे अच्छा समाधान Boost smart pointers है।

+1

बूस्ट स्मार्ट पॉइंटर्स ने इसे तकनीकी रिपोर्ट में बनाया है, इसलिए आपके पास std :: tr1 :: shared_ptr <> हो सकता है। वीएस 2008 में वीसी ++ 9 करता है। –

+0

संदर्भ के लिए C++ 0x unique_pte, जो auto_ptr के लिए बहुत अधिक प्रतिस्थापन है, रैल्यू संदर्भों के कारण कंटेनरों में काम करेगा और अर्थशास्त्र को स्थानांतरित करेगा –

8

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

आप स्मृति खुद के प्रबंधन की झुंझलाहट से बचना चाहते हैं, तो आप या एक स्मार्ट सूचक भंडारण एक shared_ptr जैसे (ध्यान दें कि auto_ptr एसटीएल कंटेनर के साथ काम नहीं करता है पर विचार कर सकते, मैक्स Lybbert के अनुसार), किसी भिन्न रूप उसके। इस तरह आप अभी भी अपनी पॉलिमॉर्फिक कक्षा का उपयोग कर सकते हैं, लेकिन यह आपके लिए थोड़ा कम काम है।

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

+0

हू। वह नहीं जानता था। कितना दुर्भाग्यपूर्ण। –

+0

मैंने कभी कोशिश नहीं की है इसलिए मैं सोच रहा हूं, auto_ptr stl कंटेनर के साथ क्यों काम नहीं करता है? –

+0

आह, हाँ। समझ में आता है। –

8

मानक एसटीएल कंटेनर के साथ shared_ptr का उपयोग करने के बजाय, Boost Pointer Container Library पर एक नज़र डालें। यह वास्तव में इस समस्या को हल करने के लिए डिज़ाइन किया गया है।

1

क्या तुमने कभी तर्क सुना है लेकिन यह इतना उन्हें संरचनाओं कॉपी करने के लिए महंगा हो जाएगा, तो हर समय जब आप एक वेक्टर में संकेत के बजाय पूर्ण वस्तुओं का उपयोग करना चाहते है, तो अपने 2 मुख्य तर्क हैं:

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

प्रतिलिपि बनाने की अतिरिक्त लागत आमतौर पर कंटेनर में सामान जोड़ते समय ली जाती है, डेटा का उपयोग करते समय नहीं - इसके बारे में थोड़ा सोचें: आप सबसे ज्यादा क्या करते हैं? आइटम जोड़ें या उनका इस्तेमाल करें?

हालांकि, पॉलिमॉर्फिकल ऑब्जेक्ट्स जोड़ने पर, स्लाइसिंग से बचने के लिए पॉइंटर्स आवश्यक हैं।

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

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