2012-09-17 17 views
7

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

क्या वह बस इसे आदत के रूप में कर रहा है या इसके लिए गति बढ़ने जैसे अच्छे कारण हैं?

  • मुझे पता है कि डेटा के अनावश्यक प्रतियों से बचने के लिए डेटा के पॉइंटर्स का उपयोग कर सकते हैं, फिर भी एक ही समय में कई कंटेनर/संरचनाओं में उस डेटा के लिए घर निर्देश।
  • इन उदाहरणों में, यह मामला नोट है। डेटा केवल उस मानचित्र में है।
+2

प्रोफेसर से क्यों न पूछें? यह एक बेवकूफ सवाल नहीं है। – John3136

+0

मैं आपको अभ्यास में बता सकता हूं कि मेरे लिए पेशेवर सी ++ विकास के 15 वर्षों से अधिक और नौकरी पर लिखे गए कोड की 1 मिलियन लाइनें हैं, मैंने शायद ही कभी एक कंटेनर के अंदर एक संरचना या कक्षा डाली है। 99% से अधिक समय मैं किसी प्रकार के सूचक का उपयोग करता हूं (हाल ही में यह एक स्मार्ट सूचक होने की संभावना है)। – drescherjm

+0

हालांकि मैंने पहले ही जवाब दिया है, मुझे आश्चर्य है कि प्रश्न को http://stackoverflow.com/questions/141337/c-stl-should-i-store-entire-objects-or-pointers-to का डुप्लिकेट माना जाना चाहिए -objects। – jogojapan

उत्तर

9

मैं इसे देखना, वहाँ तय संकेत बनाम वस्तुओं का उपयोग करने के शामिल कारकों में से एक नंबर रहे हैं:

1. आप करो या आप बहुरूपता की जरूरत नहीं है?

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

2. और वस्तुओं आप की दुकान के आकार कॉपी ऑपरेशन

प्रमुख कारण क्यों संकेत वस्तुओं के लिए preferrable हो सकता है में से एक है के लिए उनकी उपयुक्तता कि कंटेनर पर प्रदर्शन विभिन्न कार्यों का बना प्रतियां शामिल वस्तुओं में संग्रहीत वस्तुओं। यह कई भंडारण संचालन (उदाहरण के लिए std::vector<>::push_back() या std::map<>::insert()), कुछ पुनर्प्राप्ति संचालन (उदा। std::vector<>::operator[], और फिर ऑब्जेक्ट को स्थानीय चर में संग्रहीत करना) के मामले में है, और कंटेनर द्वारा "आंतरिक रूप से" किए गए कुछ संचालन, उदाहरण के लिए एक वेक्टर के पुन: आवंटन जब यह अपनी क्षमता से परे बढ़ता है, या std::unordered_map<> का रिहाशिंग करता है। ध्यान दें कि आप कैसे कंटेनर चुनते हैं और इसका उपयोग कैसे करते हैं इसके आधार पर प्रतिलिपि संचालन कम महत्वपूर्ण हो सकता है (उदा।स्टोरेज के लिए std::vector<>::emplace_back() का उपयोग करके पर्याप्त स्थान आवंटित करने के लिए std::vector<>::reserve() का उपयोग करके, और कभी भी पुनर्प्राप्त तत्व की स्थानीय प्रतिलिपि बनाने का अर्थ यह नहीं हो सकता कि कोई भी प्रतिलिपि नहीं बनाई गई है)।

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

3. अन्य संचालन आप कंटेनर पर प्रदर्शन और उसकी सामग्री

यहां तक ​​कि अगर वस्तुओं आप के साथ काम कर रहे हैं संकेत से बड़े होते हैं और आप कॉपी ऑपरेशन का एक महत्वपूर्ण राशि की उम्मीद, संकेत का उपयोग कर जरूरी preferrable नहीं है । ऐसी परिस्थिति पर विचार करें जहां आप बड़ी संख्या में मध्यम आकार की वस्तुओं को स्टोर करते हैं (कहें, प्रत्येक 16 बाइट्स) और आपको अक्सर पूरे कंटेनर पर फिर से भरने की आवश्यकता होती है और कुछ प्रकार की सांख्यिकीय गणना होती है। जब आप इन ऑब्जेक्ट्स को सीधे वेक्टर में स्टोर करते हैं, तो आपको पुनरावृत्ति के दौरान बहुत अच्छा कैश-दक्षता मिलती है: जैसे ही आप एक ऑब्जेक्ट पुनर्प्राप्त करते हैं, एक संपूर्ण कैश-लाइन स्मृति से पुनर्प्राप्त की जाएगी, इसलिए अगली कुछ ऑब्जेक्ट्स को पुनर्प्राप्त करना बहुत तेज़ होगा। आमतौर पर यह मामला नहीं होता है जब पॉइंटर्स का उपयोग किया जाता है; इसके विपरीत, तत्व को पुनर्प्राप्त करने के बाद, पॉइंटर को संदर्भित किया जाना चाहिए, जिससे स्मृति क्षेत्र से एक और चाल चलाना संभवतः कैश नहीं किया जाता है।

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


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

1

एक संभावना यह है कि सामग्री प्रकार कॉपी करने योग्य नहीं है।

1

सीधे कंटेनर में ऑब्जेक्ट इंस्टेंस को संग्रहीत करने का लाभ यह है कि आप संकेतक के स्तर से बचते हैं & जो आप पॉइंटर स्वयं उपयोग करते हैं उस स्थान पर सहेजते हैं। दोनों समय के मामले में & स्पेस दक्षता पॉइंटर्स को संग्रहीत करने के बजाय ऑब्जेक्ट इंस्टेंस को संग्रहीत करके जीत सकता है। यदि आप प्रोसेसर कैश मेमोरी कैसे काम करते हैं, इस बारे में कुछ समझते हैं, तो यह देखना मुश्किल नहीं है कि कंटेनर में "इनलाइन" ऑब्जेक्ट उदाहरणों को संग्रहीत करने से वास्तविक प्रदर्शन लाभ हो सकता है।

निहित प्रकार या कंटेनर उपयोग पैटर्न के बारे में किसी भी मान्यताओं बनाने के बिना

, डिफ़ॉल्ट कंटेनर std::vector<T> (और नहीं std::vector<T*>) होना चाहिए। उस डिफ़ॉल्ट विकल्प से शुरुआत करते हुए, आप वेक्टर के अलावा कुछ और उपयोग करेंगे यदि आप देख सकते हैं कि उपयोग पैटर्न को उस अन्य प्रकार की संरचना के प्रदर्शन प्रोफ़ाइल से कैसे फायदा होगा। इसी प्रकार, आपके पास कंटेनर स्टोर पॉइंटर्स ऑब्जेक्ट्स होगा यदि पॉइंटर इंडिकेशन आवश्यक या प्रदर्शन शर्तों में इसके लायक है। निहित प्रकार की आवश्यकता होती है यदि निहित प्रकार प्रति-निर्माण योग्य नहीं है, और यह भी आवश्यक है कि कंटेनर अपनी वस्तुओं का "स्वामित्व" न करे।

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