2012-09-16 18 views
6

मेरी कक्षा में, मेरे पास सदस्य चर std::vector<node*> childrenक्या यह पॉइंटर को वेक्टर के वेक्टर में पुश_बैक करने के लिए मेमोरी रिसाव है?

क्या निम्न श्रेणी सदस्य फ़ंक्शन मेमोरी लीक बनाता है?

//adds a child node 
{ 
    node* child = new node("blah","blah","blah"); 
    child->Set_Parent(this); 
    children.push_back(child); //<- Is this ok? 
} 

वेक्टर सूचक की एक प्रतिलिपि बनाता है और मैं एक ही स्मृति, करने के लिए दो संकेत दिए गए और फिर मूल सूचक है, है ना दायरे से बाहर चला जाता है?

यह आसान और स्पष्ट हो सकता है, लेकिन मैं बस अपनी धारणा की पुष्टि करना चाहता हूं।
धन्यवाद

+1

मेरा सुझाव है कि आप स्मार्ट पॉइंटर्स देखें, जैसे कि ['std :: shared_ptr'] (http://en.cppreference.com/w/cpp/memory/shared_ptr)। –

+3

@ जोचिमपिलबोर्ग: आप इस मामले में ['std :: unique_ptr'] (http://en.cppreference.com/w/cpp/memory/unique_ptr) का भी उपयोग कर सकते हैं, क्योंकि 'std :: vector' चाल semantics का समर्थन करता है। – bitmask

+0

यदि नोड्स हमेशा माता-पिता होने चाहिए तो आप इसे कन्स्ट्रक्टर का हिस्सा बना सकते हैं। फिर आपको केवल 'kids.push_back की आवश्यकता है (नया नोड ("ब्लाह", "ब्लाह", "ब्लाह"), यह); – dtech

उत्तर

12

यह एक रिसाव नहीं है ... अभी तक। हालांकि, यदि vector गुंजाइश से बाहर हो जाता है, या आप erase, pop_back या ऐसा कुछ और करते हैं जो वेक्टर से तत्वों को हटा देता है, बिना किसी तत्व के delete तत्व को हटाकर आप अपने हाथों पर एक रिसाव लेंगे।

ऐसा करने का सही तरीका vector<node *> से vector<unique_ptr<node>> का उपयोग करने से बदलना है। आपका कोड

//adds a child node 
{ 
    node* child = new node("blah","blah","blah"); 
    child->Set_Parent(this); 
    children.push_back(std::unique_ptr<node>(child)); 
} 

को बदलने के लिए या boost::ptr_vector<node> उपयोग करें यदि आप बूस्ट का उपयोग कर सकते हैं।

+0

हाँ, मैं कच्चे पॉइंटर्स से बच सकता हूं, लेकिन उन्हें स्मृति रिसाव को ट्रैक करने का अभ्यास नहीं मिलेगा! :) पता नहीं था कि बूस्ट की तरह एक वर्ग था! धन्यवाद –

+4

अंतिम पंक्ति बस 'children.emplace_back (बच्चे) हो सकती है; ' –

2

यदि आप वेक्टर के विनाशक वाले वर्ग को बुलाते हैं तो बच्चों के नोड को रद्द करना भूल जाते हैं, यह केवल एक स्मृति रिसाव है।

+1

रूट बनाउंगा तो मैं बस नलप्टर में जाऊंगा! धन्यवाद। हाँ, मेरा विनाशक वेक्टर के माध्यम से loops, और प्रत्येक सूचक हटा देता है। मुझे उन्हें शून्य करने के लिए कोई कारण नहीं मिला क्योंकि पॉइंटर्स जल्द ही गायब हो जाएंगे। –

1

यह एक स्मृति रिसाव नहीं है। आपके पास अभी भी वेक्टर में एक पॉइंटर है और जब आवश्यक हो तो आप स्मृति को मुक्त कर पाएंगे।

1

जब वेक्टर गुंजाइश से बाहर हो जाता है, तो यह विनाशक बिंदु-वस्तु को नष्ट नहीं करता है। यह सूचक को नष्ट कर देता है - जो कुछ भी नहीं करता है।

आपके कोड ने new के माध्यम से उस ऑब्जेक्ट को बनाया है। आपका कोड उस ऑब्जेक्ट को हटाने के लिए ज़िम्मेदार है। यदि आप ऐसा नहीं करते हैं, तो आपके पास रिसाव है। यदि आप जल्दी ऐसा करते हैं, यानी, वेक्टर से सूचक को हटाने से पहले, आपको भी बड़ी समस्याएं होती हैं।

-3

मान लीजिए children एक वर्ग सदस्य है, आप कक्षा deconstructor पर वेक्टर में बस सभी आइटम हटा देंगे।

struct Foo{}; 

class Bar 
{ 
public: 
    Bar(){}; 
    ~Bar() 
    { 
     for(vector<Foo*>::iterator it = children.begin(); it != children.end(); ++it) 
     { 
      SAFE_DELETE((*it)); //use your own macro/template or use delete if you don't have one 
      delete (*it); 
      (*it) = NULL; 
     } 
    } 
    vector<Foo*>children; 
} 

Foo* p = new Foo(); 
children.push_back(p); 

आप एक vector<Foo>child बजाय, वेक्टर मूल वस्तु की एक प्रतिलिपि बनाने हैं पर हर push_back संग्रहीत करने के लिए है, लेकिन आप संकेत का उपयोग कर रहे के बाद से, इस मामले new कोई वस्तु से ढेर पर आवंटित में प्रयोग किया जाता हैं प्रतिलिपि बनाई गई है, सूचक जो लंबे जीवनकाल ऑब्जेक्ट को इंगित करता है, बस संग्रहीत किया जाता है, जिसका अर्थ है हाँ, आपको इसे बाद में हटाना होगा।

+0

यह समझ में आता है।मुझे नहीं लगता कि मुझे उन्हें शून्य पर सेट करने की आवश्यकता है, हालांकि पूरी वस्तु नष्ट हो जाएगी। मैं मैक्रो/टेम्पलेट के उद्देश्य को समझ नहीं पा रहा हूं। –

+1

मुझे यह सही नहीं मिला, आपको नहीं लगता कि आपको इसे हटाते समय NULL को पॉइंटर सेट करने की आवश्यकता है? 'safe_delete' उम्र के लिए एक ज्ञात मैक्रो/टेम्पलेट रहा है, इसका उद्देश्य एक ढेर आवंटित आइटम को सुरक्षित रूप से हटाना है। मैं आपको डेविड मेहे और स्कॉट मेयर्स से प्रभावी/अधिक प्रभावी सी ++ पढ़ने की सलाह देता हूं। –

+4

मैं डाउनवॉटर नहीं हूं, लेकिन यह मूर्खतापूर्ण है। 'SAFE_DELETE' सुरक्षित नहीं है; यह सब जांचता है कि 'हटाएं' का आह्वान करने से पहले पॉइंटर शून्य है या नहीं। शून्य सूचक को हटाने में कुछ भी गलत नहीं है। उस परीक्षा की कोई ज़रूरत नहीं है; 'हटाएं' का उपयोग करने के बजाय 'SAFE_DELETE' का उपयोग करने की कोई आवश्यकता नहीं है। 'SAFE_DELETE' को वास्तव में सुरक्षित बनाने के लिए किसी भी तरह यह जांचना होगा कि 'हटाए जाने' से पहले 'गैर' के साथ एक गैर-शून्य सूचक वास्तव में आवंटित किया गया था या नहीं। यह ऐसा नहीं करता है। इसे हटाने के बाद पॉइंटर को 'न्यूल' पर सेट करने का कोई कारण नहीं है; हम विनाशक में हैं। –

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