2012-05-05 16 views
31

हटाएं मैं सी ++ में चीजों को हटाने के संबंध में पूरी तरह उलझन में हूं यदि मैं ऑब्जेक्ट्स की एक सरणी घोषित करता हूं और यदि मैं clear() फ़ंक्शन का उपयोग करता हूं। क्या मुझे यकीन है कि स्मृति जारी की गई थी?सी ++ वेक्टर, ऑब्जेक्ट्स, फ्री मेमोरी

tempObject obj1; 
tempObject obj2; 
vector<tempObject> tempVector; 

tempVector.pushback(obj1); 
tempVector.pushback(obj2); 

मैं सुरक्षित रूप से सभी स्मृति को मुक्त करने के स्पष्ट फोन कर सकते हैं:

उदाहरण के लिए

? या क्या मुझे एक-एक करके हटाने के लिए पुन: प्रयास करना होगा?

tempVector.clear(); 

यदि यह परिदृश्य वस्तुओं के सूचक में बदल जाता है, तो क्या उत्तर ऊपर जैसा ही होगा?

+1

दूसरे मामले से दूसरे मामले की तुलना में कुछ भी अलग नहीं है, जो कि वेक्टर को इंगित करता है। मुझे लगता है कि इस सवाल को व्यापक किया जाना चाहिए ताकि आप समझ सकें कि मेमोरी आवंटन/डीलोकेशन कैसे काम करना चाहिए, और शायद पॉइंटर्स भी। – Marlon

+0

यह कहता है कि इसे फ़ंक्शन स्टैक के अंदर घोषित करने से स्वचालित रूप से विनाशक को बंद कर दिया जाता है। https://stackoverflow.com/questions/3054567/right-way-to-deallocate-an-stdvector-object –

उत्तर

62

आप स्पष्ट कॉल कर सकते हैं, और यह सभी वस्तुओं को नष्ट कर देगा, लेकिन यह स्मृति को मुक्त नहीं करेगा। अलग-अलग तत्वों के माध्यम से पाशन मदद नहीं करेगा या तो (क्या कार्रवाई तुम भी वस्तुओं पर लेने के लिए प्रस्ताव होगा?) आप क्या कर सकते यह है:

vector<tempObject>().swap(tempVector); 

कि कोई स्मृति के साथ एक खाली वेक्टर आवंटित बना सकते हैं और यह स्वैप जाएगा TempVector के साथ, प्रभावी ढंग से स्मृति को नष्ट कर देता है।

सी ++ 11 में फ़ंक्शन shrink_to_fit भी है, जिसे आप साफ़ करने के लिए कॉल के बाद कॉल कर सकते हैं(), और यह सैद्धांतिक रूप से आकार (जो अब 0 है) फिट करने की क्षमता को कम कर देगा। हालांकि, यह एक बाध्यकारी अनुरोध है, और आपका कार्यान्वयन इसे अनदेखा करने के लिए स्वतंत्र है।

+0

उत्तर के लिए धन्यवाद। क्या आप उपरोक्त क्या बताते हैं? उसे कॉल करने के बाद, क्या मुझे स्पष्ट कॉल करने की आवश्यकता है? – mister

+3

@dupdupdup: नहीं, आपको स्पष्ट कॉल करने की आवश्यकता नहीं है। TempVector में मौजूद वस्तुओं को खाली वेक्टर में स्थानांतरित कर दिया जाता है। फिर, खाली वेक्टर, चूंकि यह एक नामहीन अस्थायी वस्तु है, नष्ट हो गया है, और इसकी सामग्री, जो पहले tempVector के स्वामित्व में थी, नष्ट हो जाती है और स्मृति को हटा दिया जाता है। –

+0

मैं कोई सी ++ विशेषज्ञ नहीं हूं, दिमाग बता रहा हूं कि यह 'tempVector.resize (0)' से बेहतर है, मैं पहले कोशिश करता हूं? – delnan

14

vector::clear() ऑब्जेक्ट्स को स्टोर करने के लिए वेक्टर द्वारा आवंटित स्मृति मुक्त नहीं करता है; यह वस्तुओं के लिए विनाशकों को बुलाता है।

उदाहरण के लिए, वेक्टर एक समर्थन दुकान के रूप में एक सरणी का उपयोग करता है और वर्तमान में 10 तत्व शामिल हैं, तो बुला clear() प्रत्येक वस्तु के नाशक सरणी, में तो वहाँ फोन करेगा लेकिन समर्थन सरणी पुनः आवंटित की जाती नहीं किया जाएगा, वेक्टर (आवंटित) को आवंटित sizeof(T) * 10 बाइट अभी भी है। size() 0 होगा, लेकिन size() वेक्टर में तत्वों की संख्या देता है, जो आवश्यक रूप से बैकिंग स्टोर का आकार नहीं है।

आपके दूसरे प्रश्न के लिए, new के साथ आवंटित कुछ भी आपको delete के साथ आवंटित करना होगा। आप आमतौर पर इस कारण से वेक्टर को पॉइंटर नहीं बनाए रखते हैं। ऐसा करने के लिए शायद ही कभी कोई अच्छा कारण होता है और जब आप स्कोप छोड़ते हैं तो वेक्टर को साफ होने से रोकते हैं। हालांकि, clear() पर कॉल करना अभी भी वैसे ही कार्य करेगा, भले ही इसे आवंटित किया गया हो।

  1. वस्तु जीवनकाल
  2. भंडारण अवधि

उदाहरण के लिए::

{ 
    vector<MyObject> v; 
    // do some stuff, push some objects onto v 
    v.clear(); // 1 
    // maybe do some more stuff 
} // 2 

1 पर, आप स्पष्ट v: यह सब नष्ट कर देता

18

वहाँ दो अलग-अलग यहाँ बातें हैं वस्तुओं को भंडारित किया गया था। प्रत्येक को अपना विनाशक कहा जाता है, अगर आपने लिखा है, और MyObject के स्वामित्व वाली किसी भी चीज़ को अब जारी किया गया है। हालांकि, वेक्टर v को बाद में आप चाहते हैं कि कच्चे भंडारण को रखने का अधिकार है।

यदि आप 1 और 2 के बीच कुछ और चीजों को धक्का देने का निर्णय लेते हैं, तो यह समय बचाता है क्योंकि यह पुरानी स्मृति का पुन: उपयोग कर सकता है।

2 में वेक्टर v दायरे से बाहर चला जाता है: किसी भी वस्तुओं आप 1 के बाद से यह में धकेल दिया नष्ट कर दिया जाएगा (के रूप में यदि आप स्पष्ट रूप से स्पष्ट फिर से बुलाया था), लेकिन अब अंतर्निहित भंडारण भी जारी किया गया है (v जीता ' इसे फिर से उपयोग करने के लिए चारों ओर नहीं हो)।


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

+0

'यदि आप धक्का देने का निर्णय लेते हैं तो इसका क्या मतलब है .. यह समय बचाता है क्योंकि यह पुरानी मेमोरी का पुन: उपयोग कर सकता है।' जब आप नई वस्तुओं को जोड़ना चाहते हैं तो पुरानी स्मृति क्यों मायने रखती है? – user13107

+0

वेक्टर को स्टोर की जाने वाली वस्तुओं के लिए आंतरिक रूप से संग्रहण का प्रबंधन करना होता है। एक नए वेक्टर बनाने के लिए नए भंडारण आवंटित करने की आवश्यकता है, लेकिन मौजूदा वेक्टर को समाशोधन और पुन: उपयोग करने से पहले से आवंटित भंडारण का पुन: उपयोग करने की अनुमति मिलती है (लेकिन इसकी गारंटी नहीं है)। – Useless

0

यदि आपको वेक्टर का बार-बार उपयोग करने की आवश्यकता है और आपका वर्तमान कोड बार-बार आपके लूप के भीतर या प्रत्येक फ़ंक्शन कॉल पर घोषित करता है, तो संभव है कि आप स्मृति से बाहर हो जाएंगे। मेरा सुझाव है कि आप इसे बाहर का ऐलान करते हैं उन्हें अपने कार्यों में संकेत दिए गए और उपयोग के रूप में पारित:

my_arr.resize() 

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

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