2010-09-17 12 views
5

हमें erase से पहले या बाद में हटा देना चाहिए। मेरी समझ दोनों ठीक है। क्या यह सही है?क्या हमें वेक्टर में पॉइंटर के लिए मिटाने से पहले या बाद में हटा देना चाहिए?

इसके अलावा, क्या कोई मामला है जब हम इसे मिटाते समय तत्व को हटाना नहीं चाहते हैं? मेरा मानना ​​है कि वहां होना चाहिए, अन्यथा, erase जिम्मेदारी लेने में खुशी होगी।

std::vector<foo*> bar; 
... 
for (vector<foo*>::iterator itr = bar.begin(); itr != bar.end(); itr++) 
{ 
    delete (*itr); //before OR 
    bar.erase(itr); 
    delete (*itr); //after??? 
} 
+0

आपका मतलब है 'std :: vector ' – sellibitze

+0

धन्यवाद। ठीक कर दिया। – pierrotlefou

+0

मेरा मानना ​​है कि आपके पास 'iter ++ 'है, अन्यथा लूप समाप्त नहीं होगा। – Naveen

उत्तर

10

"itr" इस तरह इस्तेमाल किया जाना चाहिए;

for (vector<foo*>::iterator itr = bar.begin(); itr != bar.end();) 
{ 
    delete (*itr); 
    itr = bar.erase(itr); 
} 

हालांकि, मैं पहले सभी तत्वों को हटाना पसंद करता हूं, और फिर वेक्टर साफ़ करता हूं;

for (vector<foo*>::iterator itr = bar.begin(); itr != bar.end(); ++itr) 
    delete (*itr); 
bar.clear(); 
+1

+1, मैं दूसरे संस्करण के लिए भी चयन करूंगा: इस तरह वे वेक्टर के भीतर तत्वों के उन सभी बदलावों को नहीं ले पाएंगे। कम से कम अगर मिटाने के साथ एक लूप का उपयोग कर, पिछड़ा पुनरावृत्ति अधिक उपयुक्त होगा। –

+0

मैं सहमत हूं, लेकिन, मुझे यकीन नहीं है कि क्या वेक्टर :: मिटा एक रिवर्स_इटरेटर (इसे सोचने के लिए थकने के लिए संगत है) –

+0

आपको पसंदीदा समाधान का उपयोग करना चाहिए। ** ओ (एन^2) ** के विपरीत ** ओ (एन) ** है। – kevlar

4

तत्व को मिटाने के लिए एक इटरेटर का उपयोग करने से इटरेटर को अमान्य कर दिया जाता है। इसे मिटाने से पहले आइटम को हटाना चाहिए।

आपको अपने अगले लूप पुनरावृत्ति के लिए मिटाने से रिटर्न वैल्यू का भी उपयोग करना चाहिए।

+0

सामान्य रूप से अच्छी टिप्पणियां लेकिन क्या आप हमें बता सकते हैं कि "इसे मिटाए जाने से पहले आपको आइटम को हटाना चाहिए" के पीछे क्या कारण है। मुझे नहीं लगता कि यह मामला क्यों होना चाहिए। असल में मुझे लगता है कि रिवर्स अधिक सुरक्षित होगा (यानी मल्टीथ्रेड कोड में)। दोष यह है कि आपको मिटाए जाने से पहले पॉइंटर का अस्थायी रूप से पॉइंटर रखना होगा या आप इसे हटाने में सक्षम नहीं होंगे। मुझे यह एक बड़ा फायदा नहीं दिख रहा है, इसलिए इसकी अनुशंसा नहीं की जाएगी लेकिन जिस तरह से आप आपका उत्तर शब्द यह ऐसा लगता है कि पहले हटाना एकमात्र तरीका है। – n1ckp

+0

@ n1ck: वह दो प्रकारों (यानी पहले या बाद में) के बीच पूछ रहा था। मैं बस सवाल को संबोधित कर रहा था। बेशक आप पॉइंटर को अस्थायी रूप से ले जा सकते हैं, लेकिन उन्हें जगहों पर हटाने से अधिकांश अनुप्रयोगों के लिए भी काम करता है। – Paul

+0

हार्वे: निश्चित रूप से, मैंने अभी कहा है कि आपका शब्द शायद सबसे अच्छा नहीं था क्योंकि ऐसा लगता है कि यह एकमात्र तरीका है। मुझे लगता है कि पाठक को समझने में सक्षम होना चाहिए, लेकिन मैं बस पूरी तरह स्पष्ट होना चाहता था। – n1ckp

1

erase करना vector इटरेटर को अमान्य कर देगा। तो *iter अपरिभाषित व्यवहार का आह्वान करेगा। इसलिए आपको erase के बाद delete करने की आवश्यकता है। इसके अलावा, आप erasevector के तत्वों को इसके माध्यम से सक्रिय करते समय नहीं कर सकते हैं (इसी कारण से, iter अमान्य हो गया है इसलिए iter++ अमान्य है)। इस मामले में आप लूप के अंदर से erase कॉल को हटा सकते हैं और लूप के बाहर वेक्टर के clear कर सकते हैं।

2

वेक्टर की प्रकृति है कि पहला तत्व को मिटाकर पूरे सरणी का कारण बनता है आगे शिफ्ट करने के लिए, निम्नलिखित इस आपरेशन कोशिश कम करने के लिए:

std::vector<foo*> v1; 
//... 
while(!v1.empty()) 
{ 
    delete v1.back(); 
    v1.pop_back(); 
} 

वैसे - इस विधि के किसी भी iterators को अमान्य नहीं करता है (केवल मिटाए गए आइटमों पर)

3

इसके अलावा, क्या कोई मामला है जब हम इसे मिटाते समय तत्व को हटाना नहीं चाहते हैं?

कैसे वेक्टर संभवतः यह जान सके कि किसी और की जरूरत है वस्तुओं की ओर इशारा किया? यह कैसे पता चलेगा कि पॉइंट्स ढेर पर संग्रहीत हैं? वेक्टर में स्थैतिक या स्वचालित वस्तुओं के पॉइंटर्स, या यहां तक ​​कि लटकने वाले पॉइंटर्स को पॉइंटर्स रखना पूरी तरह से संभव है।

std::vector<std::unique_ptr<foo>> vec; 

अब आप कुछ भी मैन्युअल रूप से हटाने के लिए की जरूरत नहीं है:

C++ 0x आप को व्यक्त करने कि वेक्टर pointees ही चाहिए अनुमति देता है। अद्वितीय पॉइंटर्स को मिटाने से, उनके संबंधित पॉइंट भी हटा दिए जाते हैं। आधुनिक सी ++ में देशी पॉइंटर्स के कंटेनर बहुत दुर्लभ हैं।

यदि आपके पास सी ++ 0x कंपाइलर नहीं है, तो आप इसके बजाय std::vector<boost::shared_ptr<foo> > या boost::ptr_vector<foo> का उपयोग कर सकते हैं। std::tr1 या std नेमस्पेस में #include <memory> में आधुनिक कंपाइलर shared_ptr आपूर्ति करते हैं।

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

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