2012-03-27 23 views
5

मैं objList में 10 Obj ऑब्जेक्ट को स्टोर करना चाहता हूं, लेकिन मुझे नहीं पता कि इस मामले में delete उचित उपयोग कब होता है। यदि मैं नीचे दिए गए कोड में delete Obj; का उपयोग करता हूं, जहां मैं नीचे कोड में नोट करता हूं, तो Obj अभी भी objList में संग्रहीत किया जाएगा?"हटाएं" का उपयोग कब करें?

struct Obj { 
    int u; 
    int v; 
}; 

vector<Obj> objList; 

int main() { 
    for(int i = 0; i < 10; i++) { 
     Obj *obj = new Obj(); 
     obj->u = i; 
     obj->v = i + 1; 
     objList.push_back(*obj); 
     // Should i use "delete Obj;" here? 
    } 
} 
+5

'नई' की आवश्यकता नहीं है .. ऑब्जेक्ट को 'ओब्ज obj;' का उपयोग करके ढेर पर बनाएं। – Naveen

+1

और यहां तक ​​कि यदि आपको 'नया' की आवश्यकता है, तो एक सरल 'हटाएं' पर्याप्त नहीं होगा - अगर 'push_back' फेंकता है, तो आपको रिसाव मिल गया है। गतिशील संसाधनों को प्रबंधित करने के लिए आपको हमेशा [स्मार्ट पॉइंटर्स] (http://stackoverflow.com/questions/106508) या अन्य [RAII] (http://stackoverflow.com/questions/76796) ऑब्जेक्ट्स का उपयोग करना चाहिए। –

उत्तर

8

आप ढेर पर बनाने के साथ new जरूरतों से हटाए जाने की किसी भी वस्तु delete। आपके कोड में, आप वास्तव में अपने संग्रह में एक प्रतिलिपि संग्रहीत कर रहे हैं।

objList.push_back(*Obj); 

क्या इस लाइन चरण दर चरण कर रहा है:

  1. अंतर्निहित ढेर स्मृति Obj पर है करने के लिए एक सूचक Indirecting
  2. (वस्तु Obj लौटने) प्रतिलिपि निर्माता कॉलिंग एक अस्थायी बनाने के लिए कॉपी
  3. संग्रह में अस्थायी प्रतिलिपि भंडारण

यो आपको ढेर पर इस प्रारंभिक ओब्जे को बनाने की ज़रूरत नहीं है, स्थानीय आवंटित एक स्टैक पर्याप्त होगा क्योंकि लूचियन ग्रिगोर ने बताया है।

Obj obj; 
objList.push_back(obj); 

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

यदि आप अपनी वस्तुओं को std::shared_ptr द्वारा संग्रहीत करते हैं तो यह बेहतर होगा। इस तरह से हटाया जाएगा जब ओबीजे के सभी संदर्भ हटा दिए गए थे।

std::vector< std::shared_ptr<Obj> > vec; 
vec.push_back(std::make_shared(new Obj())); 
+0

ध्यान दें कि यह पॉइंटर्स की एक सरणी नहीं है, लेकिन ऑब्जेक्ट्स। –

+0

मैं संग्रह द्वारा आवंटित ढेर अंतरिक्ष में वस्तु के जीवनकाल को इंगित करने की कोशिश कर रहा था, ओपी द्वारा प्रबंधित नहीं किया जाना चाहिए। :-) – Konrad

+0

इसके अलावा, यह ढेर और ढेर नहीं है, लेकिन स्वचालित और गतिशील भंडारण है। –

9

हां, आपको चाहिए।

आपके कार्यक्रम में प्रत्येक new के लिए delete होना चाहिए।

लेकिन अपने कार्यक्रम गतिशील आवंटन की जरूरत नहीं है:

Obj obj; 
obj.u = i; 
obj.v = i + 1; 
objList.push_back(obj); 

इसके अलावा, अपने वाक्य रचना गलत था - objList.push_back(*Obj); // should be *obj, not *Obj

3

क्या होता है के बारे में सोचो:

अपने पाश में आप Obj का एक नया उदाहरण बना सकते हैं और इसे करने के लिए कुछ मान निर्दिष्ट। यह उदाहरण आपके ढेर पर बनाया गया है - इस प्रकार आपको इसे बाद में मुक्त करना होगा। जब आप वेक्टर में उदाहरण जोड़ते हैं तो आप इसकी एक प्रतिलिपि बनाते हैं - क्योंकि आपके पास ऑब्जेक्ट्स का वेक्टर होता है, पॉइंटर्स की नहीं। इस प्रकार वेक्टर ओबीजे की अपनी प्रति रखता है। आप अपने ओबीजे उदाहरण को मिटाने के लिए सुरक्षित हैं।

BTW

:

  • तुम भी अपने पाश
  • यह ढेर पर Obj उदाहरण आवंटित करने के लिए आवश्यक नहीं है

Obj एक्स के बाहर वस्तु दृष्टान्त पुन: उपयोग और बना सकते हैं और मुक्त कर सकता है यह ; x.u = i; x.v = i + 1; objList.push_back (x);

भी

आप स्मार्ट संकेत और स्मार्ट सूचक कंटेनरों के बारे में कुछ लेख पढ़ना चाहिए करना होगा। उदाहरण के लिए। boost :: scoped_ptr, boost :: shared_ptr, std :: auto_ptr। इन प्रतिमानों का उपयोग करने के लिए आमतौर पर स्वयं को हटाने की आवश्यकता नहीं होती है।

2

आप ढेर का उपयोग करना चाहते हैं, इसलिए मैं सुझाव देता हूं कि वेक्टर के वेक्टर को अपने वेक्टर घोषणा को बदल दें, ऐसा कुछ।

vector<Obj *>objList; 

क्यों? क्योंकि यदि यह ओब्जे के वेक्टर हैं, तो जो चीजें आप संग्रहित कर रहे हैं वे वास्तव में आपके द्वारा बनाए गए पॉइंटर्स के मूल्य ओब्ज की प्रतियां हैं। objList के आइटम और आपके द्वारा बनाए गए ओबीजे पॉइंटर्स पूरी तरह से अलग और असंबंधित हैं! तो जब आप

delete obj 

objList पर बातें पूरी तरह से पूरी तरह से अप्रभावित किसी भी तरह से कर रहे हैं।
इसके अलावा, vector<Obj> (कोई तारांकन), Obj के रूप में अपनी आइटम संग्रहीत करता है और वे ढेर पर, वे जब अपने कार्यक्रम दायरे से बाहर चला जाता है गायब हो जाएगा रहे हैं!

1

अच्छा, सरल नियम यह है कि new द्वारा निर्मित प्रत्येक चर delete द्वारा साफ किया जाना चाहिए।

हालांकि आपके लक्ष्य के आधार पर, आपको delete लिखने की आवश्यकता नहीं हो सकती है।

घर पर, स्मृति प्रबंधन के गोर विवरणों को सीखते समय, आप शायद लिखेंगे क्योंकि आप new लिखते हैं।

पेशेवर, हालांकि, कभी भी आवेदक कोड (*) में delete का उपयोग नहीं करते हैं। delete एक कोड गंध है। यह अपवादों की उपस्थिति में स्मृति रिसाव का सबसे छोटा तरीका है। पेशेवर सुरक्षित रूप से अपवादों से निपटने के लिए आरएआईआई का उपयोग करते हैं, और अर्थात्: स्मार्ट पॉइंटर्स/स्मार्ट कंटेनर।

(*) लाइब्रेरी कोड के विपरीत, यानी किसी ने लिखा कि shared_ptr कक्षा एक दिन।

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