2010-09-14 24 views
5

मैं पॉइंटर वेक्टर में मेमोरी कैसे मुक्त कर सकता हूं? कोड यह रहा:मैं पॉइंटर वेक्टर कैसे मुक्त कर सकता हूं?

class A 
{ 
    private: 
     int x,y,z; 
    public: 
     A(param1, param2, param3) 
     { 
      x=param1; 
      y=param2; 
      z=param3; 
     } 
     ~A() 
     { 
      //prompts an alertbox, warning me about the successful call of the destructor; 
     } 
}; 

... 
vector<A*> list; 
list.push_back(new A(1,2,3)); 

list.erase(list.begin()+index);//SHOULD delete the object from the memory; 
list.clear(); 

मुझे लगता है कि .erase() पता चला मेमोरी खाली नही करता, और नाशक कॉल; मैंने पुनरावृत्ति के साथ प्रत्येक सूची प्रविष्टि पर delete का उपयोग करने का प्रयास किया, लेकिन एक पुनरावृत्ति के बाद दुर्घटनाग्रस्त हो गया। किसी भी त्रुटि से बचने के लिए, सूची प्रविष्टि पहले से ही पूर्ण है, पहले ही जांच की गई है। क्या मुझे कुछ याद आ रही है? इसके अलावा, मुझे केवल एसटीएल का उपयोग करना होगा, बूस्ट की आवश्यकता नहीं है।

+0

ध्यान दें कि 'NULL' सूचक पर 'हटाएं' को कॉल करना सुरक्षित है। –

+4

आप बूस्ट पीआरटी कंटेनर लाइब्रेरी से 'बूस्ट :: ptr_vector' का उपयोग करना चाहेंगे। –

+3

सादा 'ए' कब करेंगे, 'ए *' का उपयोग क्यों करें? –

उत्तर

0
 
for(size_t i = 0; i < list.size(); ++i) 
{ 
    delete list[i]; 
} 

list.clear(); 

यदि आप ऐसा कुछ करते हैं और आपका कोड क्रैश हो जाता है, तो सटीक कोड और क्रैश जानकारी पोस्ट करें।

+0

यहां इटरेटर्स का उपयोग करना अधिक कुशल और कंटेनर स्वतंत्र होगा (यानी आप बाद में यादृच्छिक पहुंच समर्थन सूची में स्विच कर सकते हैं)। –

8

list.erase अपने सदस्य तत्वों के लिए स्मृति को हटा देगा (और उनके विनाशकों को बुलाएगा, यदि वे मौजूद हैं); यह उन पर delete पर कॉल नहीं करेगा।

एक बूस्ट shared_ptr ऐसा करने का स्पष्ट तरीका होगा। यदि आप इसका उपयोग नहीं करना चाहते हैं, तो आप या तो erase पर कॉल करने से पहले प्रत्येक पॉइंटर पर list के माध्यम से अपनी खुद की स्मार्ट-पॉइंटर क्लास लिखने के लिए जा रहे हैं, या delete पर कॉल करें। आप की तरह कुछ के साथ बड़े करीने से ऐसा कर सकते हैं:

void my_delete(A *p) 
{ 
    delete p; 
} 

... 

std::for_each(list.begin(), list.end(), my_delete); 
+3

+1: हमेशा, हमेशा स्मार्ट पॉइंटर्स का उपयोग करें जबतक कि आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं। – Puppy

+1

@DeadMG, हाँ मुझे साझा_प्टर के साथ चक्रीय निर्भरताओं के बारे में और बताएं :-) –

+3

@ ओली, shared_ptr निश्चित रूप से स्पष्ट तरीका नहीं है क्योंकि वास्तव में इन वस्तुओं को साझा करने का कोई इरादा नहीं है। std :: unique +ptr सी ++ 0x से, बूस्ट के ptr_vector या बदतर मामले में - घुसपैठ पीआरआर अधिक स्पष्ट विकल्प प्रतीत होता है। –

4
for(std::vector<A*>::iterator i = list.begin(), endI = list.end(); i != endI; ++i) 
{ 
    delete *i; 
} 
list.clear(); 

या, नए लैम्ब्डा कार्यों

std::for_each(list.begin(), list.end(), [](A* element) { delete element; }); 
list.clear(); 
+0

+1 जिस तरह से इसका उत्तर दिया जाना चाहिए था। – rubenvb

+0

मेरी इच्छा है कि यह काम कर रहा था ... यह मुझे पहले की तरह ही त्रुटियों देता है। – Tibor

+0

मुझे नहीं पता कि यह कहां दुर्घटनाग्रस्त हो सकता है, लेकिन मुझे लगभग निश्चित है कि यह for_each लूप में नहीं है। हो सकता है कि आप विनाश के बाद हटाए गए कुछ वस्तुओं तक पहुंच रहे हों, जो निश्चित रूप से एक दुर्घटना को उकसाएगा। –

3

erase केवल मिटा देता है कि वे क्या हो सकता है के बारे में कुछ भी करने के बिना क्या वेक्टर (संकेत) में है का उपयोग करते हुए पर संकेत दो।

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

मेरी सलाह किसी भी को स्वयं से संभालने से बचने के लिए होगी, और इसके बजाय Boost ptr_vector का उपयोग करने पर विचार करें।

+1

भले ही ओपी ने बूस्ट का उपयोग न करने के लिए कहा, फिर भी मैं यह जवाब पसंद करता हूं। बूस्ट के बिना सी ++ में प्रोग्रामिंग बैक में बंधे हाथ से चढ़ने जैसा है: संभव है, लेकिन बेवकूफ। –

2

विनाश पर, एक एसटीएल कंटेनर इसमें मौजूद वस्तुओं को नष्ट कर देगा। यदि वे वस्तुएं पॉइंटर्स हैं, तो यह पॉइंटर्स को नष्ट कर देगी। नग्न, गूंगा पॉइंटर्स के लिए, यह उन वस्तुओं को हटा नहीं देगा जिन्हें वे पर इंगित करते हैं। यही कारण है कि इसके लिए स्मार्ट पॉइंटर्स का उपयोग करना आमतौर पर सबसे अच्छा होता है। स्मार्ट पॉइंटर्स वे ऑब्जेक्ट्स को हटा देंगे जिन्हें वे हटाने पर संदर्भित करते हैं; std::shared_ptr पॉइंटर्स की प्रतिलिपि बनाने का ट्रैक रखता है और किसी दिए गए ऑब्जेक्ट के कितने संदर्भ मौजूद हैं, और अंतिम पॉइंटर मरने पर केवल ऑब्जेक्ट को हटा देगा। एक सूट स्मार्ट पॉइंटर की तलाश करते समय यह हमेशा अच्छा पहला उम्मीदवार होता है। आपका कंटेनर तो इस तरह की घोषणा की जाएगी: std::vector< std::shared_ptr<A> >

हालांकि, अपने संकलक/एसटीडी lib std::shared_ptr, जो अगले सी ++ मानक, अगले साल आम तौर पर उम्मीद की एक विशेषता है के साथ नहीं आ सकते हैं। हालाँकि इस बात पर std::tr1::shared_ptr के साथ आ सकता है, इस 2003 से एक TR1 सुविधा है (यदि सब और विफल रहता है, को बढ़ावा देने boost_shared_ptr है, लेकिन आप पहले से ही बढ़ावा की संभावना से इनकार।)

आप कर सकते हैं मैन्युअल रूप से प्रबंधित गतिशील आवंटित एसटीएल में वस्तुओं कंटेनर, लेकिन यह एक बोझ है और त्रुटियों के लिए प्रवण है। उदाहरण के लिए, आपको कार्यों को return कथन या अपवादों के माध्यम से प्रारंभिक (मैन्युअल क्लीनअप से पहले) लौटने से रोकना होगा, और आपको कंटेनरों पर कॉपी ऑपरेशंस के लिए देखना होगा।(अन्यथा दो कंटेनरों में वही ऑब्जेक्ट्स का जिक्र करने वाले पॉइंटर्स होंगे, जिन्हें आप दो बार नष्ट करने का प्रयास कर सकते हैं।)
मैन्युअल रूप से संसाधनों का प्रबंधन करना एक पिटा है, त्रुटियों से ग्रस्त है, और सर्वोत्तम से बचा है।

1

आपके द्वारा पोस्ट किया गया कोड वैध C++ नहीं है। इसके अलावा, मिटाएं आपके द्वारा आवंटित वस्तुओं को हटा नहीं देती है, यह केवल वेक्टर की सामग्री मिटा देती है, जो आपके मामले में पॉइंटर्स हैं। आपके द्वारा आवंटित वास्तविक वस्तुओं को हटाया नहीं जा रहा है।

#include <vector> 
#include <algorithm> 

class A 
{ 
    int x,y,z; 

public: 
    A (int param1, int param2, int param3) : 
     x (param1), y (param2), z (param3) 
    { 
    } 
}; 

struct Deleter 
{ 
    template <typename T> 
    void operator() (T *obj) const 
    { 
     delete obj; 
    } 
}; 

int 
main() 
{ 
    std::vector<A*> list; 

    list.push_back (new A (1, 2, 3)); 
    list.push_back (new A (4, 5, 6)); 
    list.push_back (new A (7, 8, 9)); 

    std::for_each (list.begin(), list.end(), Deleter()); 
    list.clear(); 
} 

तुम भी Boost Ptr Container पुस्तकालय है कि एक सुरक्षित और पुन: प्रयोज्य ढंग से इस समस्या का हल पर विचार कर सकता: यहाँ तुम क्या चाहते करने का एक सही तरीका है। सी ++ 0x में, एक std :: unique_ptr टेम्पलेट क्लास है जो जंगम अर्थशास्त्र का समर्थन करती है और स्वचालित रूप से मेमोरी को साफ करने के लिए एसटीएल कंटेनर और एल्गोरिदम के साथ उपयोग की जा सकती है।

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