2009-06-01 12 views
27

मैं इस तरह कोड है:सी ++ पॉइंटर के लिए डिफ़ॉल्ट कन्स्ट्रक्टर क्या है?

class MapIndex 
{ 
private: 
    typedef std::map<std::string, MapIndex*> Container; 
    Container mapM; 

public: 
    void add(std::list<std::string>& values) 
    { 
     if (values.empty()) // sanity check 
      return; 

     std::string s(*(values.begin())); 
     values.erase(values.begin()); 
     if (values.empty()) 
      return; 

     MapIndex *mi = mapM[s]; // <- question about this line 
     if (!mi) 
      mi = new MapIndex(); 
     mi->add(values); 
    } 
} 

मुख्य चिंता मेरे पास है, चाहे mapM [एस] अभिव्यक्ति संदर्भ वापसी होगी सूचक शून्य पर अगर नया आइटम मानचित्र में जुड़ना है?

SGI docs इस कहते हैं: DATA_TYPE & ऑपरेटर [] (स्थिरांक key_type & ट) वस्तु है कि एक विशेष कुंजी के साथ जुड़ा हुआ है के लिए एक संदर्भ देता है। यदि मानचित्र में पहले से कोई ऑब्जेक्ट नहीं है, तो ऑपरेटर [] डिफ़ॉल्ट ऑब्जेक्ट data_type() को सम्मिलित करता है।

तो, मेरे सवाल यह है कि डिफ़ॉल्ट वस्तु DATA_TYPE की प्रविष्टि() एक शून्य सूचक पैदा करेगा, या यह गलत सूचक स्मृति में कहीं ओर इशारा करते हुए बना सकते है?

उत्तर

20

यह एक NULL (0) सूचक है, जो वैसे भी गलत सूचक :)

+5

मुझे बुरा नहीं लगता कि यह अमान्य है, लेकिन यह "सुरक्षित" होना चाहता है। आप आसानी से 0 सूचक की जांच कर सकते हैं और आप इसे "हटाएं" पर कॉल कर सकते हैं। इस बारे में पढ़ने के लिए कोई संदर्भ (यूआरएल)? –

+0

मेरे पास हाथ में कोई संदर्भ नहीं है। लेकिन मुझे पूरा यकीन है कि एक पॉइंटर कन्स्ट्रक्टर इसे 0 तक शुरू करेगा (जैसे सभी इंटीग्रल प्रकारों, जैसे 'int',' short', ...)। –

+20

सी ++ मानक, 8.5 अनुच्छेद 5: 'डिफ़ॉल्ट रूप से टाइप प्रकार के किसी ऑब्जेक्ट को प्रारंभ करने का अर्थ है: अन्यथा (न तो गैर-पीओडी और न ही सरणी), ऑब्जेक्ट शून्य-प्रारंभिक है।' बस ऊपर दी गई कुछ पंक्तियां: 'टाइप टी के किसी ऑब्जेक्ट को शून्य-प्रारंभ करने का अर्थ है: यदि टी स्केलर प्रकार (3.9) है, तो ऑब्जेक्ट को 0 (शून्य) के मान में सेट किया जाता है; उसी मानक में, 3.9, अनुच्छेद 10: 'अंकगणितीय प्रकार (3.9.1), गणना प्रकार, सूचक प्रकार, और सदस्य प्रकार (3.9.2) के सूचक, [...] सामूहिक रूप से स्केलर प्रकार कहा जाता है।' तो हाँ, एक पॉइंटर डिफ़ॉल्ट रूप से 0 –

2

अभिव्यक्ति data_type() एक डिफ़ॉल्ट-प्रारंभ वस्तु का आकलन करती है पैदा हो जाएगी। गैर-पीओडी प्रकारों के मामले में, डिफ़ॉल्ट कन्स्ट्रक्टर का आह्वान किया जाता है, लेकिन पीओडी प्रकारों के मामले में, जैसे पॉइंटर्स, डिफ़ॉल्ट प्रारंभिक शून्य प्रारंभिकता के बराबर है।

तो हाँ, आप अपने मानचित्र पर NULL पॉइंटर बनाने पर भरोसा कर सकते हैं। एक स्पष्टीकरण के लिए, आप Pseudo Constructor Initializers देख सकते हैं।

18

हां यह शून्य (शून्य) सूचक होना चाहिए क्योंकि एसएलएल कंटेनर डिफ़ॉल्ट रूप से संग्रहीत वस्तुओं को प्रारंभ करेंगे जब वे स्पष्ट रूप से संग्रहीत नहीं होते हैं (यानी मानचित्र में एक गैर-मौजूद कुंजी को एक्सेस करना जैसे आप एक वेक्टर को बड़े आकार में बदल रहे हैं या आकार बदल रहे हैं आकार)।

सी ++ स्टैंडर्ड, 8.5 अनुच्छेद 5 राज्यों:

डिफ़ॉल्ट आरंभ करने के लिए प्रकार टी की एक वस्तु का अर्थ है:

  • हैं टी एक गैर पॉड वर्ग प्रकार (खंड वर्ग) है, टी 0 के लिए डिफ़ॉल्ट कन्स्ट्रक्टर कहा जाता है (और प्रारंभिक बीमार है यदि टी कोई सुलभ डिफ़ॉल्ट कन्स्ट्रक्टर नहीं है)
  • यदि टी एक सरणी प्रकार है, तो प्रत्येक तत्व डिफ़ॉल्ट है -
  • अन्यथा, ऑब्जेक्ट के लिए भंडारण iszero- प्रारंभिक है।

तुम भी है कि डिफ़ॉल्ट initialisation को ध्यान देना चाहिए बस निर्माता ommiting लिए अलग है। जब आप कन्स्ट्रक्टर को छोड़ देते हैं और बस एक साधारण प्रकार घोषित करते हैं तो आपको एक अनिश्चित मूल्य मिलेगा।

int a; // not default constructed, will have random data 
int b = int(); // will be initialised to zero 
3

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

MapIndex *mi = mapM[s]; // <- question about this line 
if (!mi) 
    mi = new MapIndex(); 
mi->add(values); 

को बदला जाना चाहिए:

MapIndex* &mi = mapM[s]; // <- question about this line 
if (!mi) 
    mi = new MapIndex(); 
mi->add(values); 

मैं हैरान कोई भी इस पर ध्यान कर रहा हूँ।

0

दुर्घटना के बारे में सुनिश्चित नहीं हैं, लेकिन definetely इस बयान के रूप में स्मृति रिसाव

अगर (मील!) मील = नए MapIndex();

हमेशा सत्य लौटता है, क्योंकि पॉइंटर मील का संदर्भ नहीं है कि मानचित्रम के विशेष मूल्य के लिए क्या है।

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