2009-07-24 17 views
17

में पॉइंटर सदस्य का उपयोग कब करना चाहिए, सी ++ (और डायरेक्ट 3 डी, लेकिन कुछ समय पहले) सीखते समय मेरे लिए भ्रमित करने वाली चीज़ में से एक है जब आपको कक्षा में पॉइंटर सदस्य का उपयोग करना चाहिए। उदाहरण के लिए, मैं एक गैर सूचक घोषणा का उपयोग कर सकते हैं:सी ++ - मुझे कक्षा

private: 
    SomeClass instance_; 

या मैं एक सूचक घोषणा

private: 
    Someclass * instance_ 

इस्तेमाल कर सकते हैं और फिर निर्माता में इस पर नए का उपयोग()।

मैं समझता हूं कि अगर कुछ क्लास किसी अन्य वर्ग से प्राप्त किया जा सकता है, तो COM ऑब्जेक्ट या एबीसी है तो यह एक सूचक होना चाहिए। क्या कोई अन्य दिशानिर्देश हैं जिनके बारे में मुझे अवगत होना चाहिए?

उत्तर

17

एक संकेतक लाभ निम्नलिखित है:

क) आप एक आलसी आरंभीकरण, पहली वास्तविक उपयोग से पहले init करने के लिए/बनाने वस्तु केवल छोटे मतलब यह है कि कर सकते हैं।

बी) डिज़ाइन: यदि आप बाहरी वर्ग प्रकार के सदस्यों के लिए पॉइंटर्स का उपयोग करते हैं, तो आप अपनी कक्षा के ऊपर एक आगे की घोषणा कर सकते हैं और इस प्रकार आपके शीर्षलेख में उस प्रकार के शीर्षलेखों को शामिल करने की आवश्यकता नहीं है - इसके बजाय आप अपने .cpp में तीसरे पक्ष के शीर्षलेख शामिल करते हैं - जिसका संकलन समय कम करने का लाभ होता है और कई अन्य शीर्षकों सहित साइड इफेक्ट्स को रोकता है।

class ExtCamera; // forward declaration to external class type in "ExtCamera.h" 

class MyCamera { 
public: 
    MyCamera() : m_pCamera(0) { } 

    void init(const ExtCamera &cam); 

private: 
    ExtCamera *m_pCamera; // do not use it in inline code inside header! 
}; 

ग) सूचक कभी भी हटाया जा सकता है - तो आप Livetime के बारे में अधिक नियंत्रण है और एक वस्तु को फिर से बना सकते हैं - एक विफलता के मामले में, उदाहरण के लिए।

+2

आलसी प्रारंभिकरण के लिए, जब भी संभव हो, मैं 'boost :: वैकल्पिक' का उपयोग करने की सलाह दूंगा। यह सूचक से सुरक्षित है क्योंकि आप इस पर अंकगणित नहीं कर सकते हैं। –

+1

लेकिन कई (मेरे जैसे) बूस्ट का उपयोग नहीं करते हैं - इसलिए यह एक बहुत ही मंच और ढांचा स्वतंत्र तरीका है ;-) ... उदाहरण के लिए मैं केवल क्यूटी :-) – 3DH

+1

का उपयोग करता हूं लेकिन जो लोग 'बूस्ट' का उपयोग नहीं करते हैं :) – GManNickG

10

यदि आप कर सकते हैं तो फ्री-स्टोर से, यदि आप कर सकते हैं तो इसे स्टैक पर आवंटित करें। यहां एक similar question है, जहां आपको सभी "क्यों है" मिलेंगे।

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

17

पॉइंटर का उपयोग करने के फायदे 3 डीएच द्वारा रेखांकित हैं: आलसी प्रारंभिकता, हेडर निर्भरताओं में कमी, और वस्तु के जीवनकाल पर नियंत्रण।

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

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

अंत में, गैर-सूचक सदस्यों तक पहुंच तेजी से होने की संभावना है, क्योंकि वे स्मृति में संगत हैं। दूसरी ओर, ढेर पर आवंटित ऑब्जेक्ट को इंगित करने वाले पॉइंटर डेटा सदस्य तक पहुंचने से कैश मिस का कारण बन सकता है, जिससे इसे धीमा कर दिया जाता है।

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

3

पॉइंटर्स का उपयोग करने का एक और कारण गतिशील बाध्यकारी होगा। यदि आपके पास वर्चुअल विधि और कुछ व्युत्पन्न कक्षाओं के साथ बेस क्लास है, तो आप पॉइंटर्स का उपयोग करके केवल गतिशील बाध्यकारी प्राप्त कर सकते हैं।

+2

यह बिल्कुल सही नहीं है - आप संदर्भों के साथ गतिशील बाध्यकारी हो सकते हैं। – boxofrats

+1

बहुत सच है, स्पष्टीकरण के लिए धन्यवाद। –

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