2013-07-25 8 views
8

मैं स्ट्रिंग मानों को MyType * पर मैप करने के लिए std::map का उपयोग कर रहा हूं। मेरे मानचित्र घोषणा इस तरह दिखता है:पॉइंटर मानों वाले मानचित्र को नष्ट करने का उचित तरीका

map<string, MyType *> *my_map = new map<string, MyType>; 

my_map मेरी वर्गों में से एक के लिए एक निजी सदस्य चर रहा है। मेरी समस्या यह है कि मैं मानचित्र को नष्ट करने के बारे में अनिश्चित हूं। मानचित्र को हटाते समय, मैं मानचित्र में निहित MyType * पर delete पर भी कॉल करना चाहूंगा।

my_map->erase(my_map->begin(), my_map->end()); 
delete my_map; 

इस संकेत दिए गए मानचित्र में निहित नष्ट करेगा, या मैं मिटा कॉल करने से पहले मानचित्र के माध्यम से पुनरावृति करने के लिए प्रत्येक सूचक हटाने की आवश्यकता है: यहाँ मेरे वर्तमान नाशक है?

+2

बाद में - 'मानचित्र' (और मानक लाइब्रेरी में अधिकांश (यदि नहीं सभी?) कंटेनर) को विनाश पर शामिल किसी भी सूचक को हटाने के लिए डिज़ाइन नहीं किया गया है। – Nbr44

+0

ठीक है धन्यवाद। जिस दस्तावेज़ पर मैंने पढ़ा था वह बहुत स्पष्ट नहीं था। यह पढ़ता है: 'यह प्रभावी रूप से हटाए गए तत्वों की संख्या से कंटेनर आकार को कम कर देता है, जो नष्ट हो जाते हैं।' – Max

+3

यह एक आम गलतफहमी है - _pointers_ स्वयं वास्तव में नष्ट हो जाते हैं, लेकिन यह उस स्मृति स्थान की स्थिति को नहीं बदलता है जो वे इंगित करते हैं । – Nbr44

उत्तर

9

पॉइंटर्स केवल इंगित करें। कच्चे पॉइंटर्स का उपयोग करते समय, आपको यह जानना होगा कि आपके ऐप का कौन सा हिस्सा उन संसाधनों का मालिक है जो पॉइंटर्स इंगित करते हैं। यदि वे मानचित्र के स्वामित्व में हैं, तो मानचित्र को नष्ट करने से पहले आपको मानचित्र पर फिर से भरना होगा और प्रत्येक पॉइंटर पर हटा देना होगा। लेकिन यदि मानचित्र केवल उन ऑब्जेक्ट्स पर पॉइंटर्स रखता है जो आपके कोड के अन्य हिस्सों के स्वामित्व में हैं, तो आपको कुछ भी करने की आवश्यकता नहीं है।

ऑब्जेक्ट जीवनकाल प्रबंधित करने के लिए shared_ptr का उपयोग करने के लिए एक सुरक्षित समाधान है, जो सुनिश्चित करेगा कि अंतिम साझा_प्टर नष्ट होने पर ऑब्जेक्ट ठीक से हटा दिया जाएगा। आप मानचित्र के अंदर shared_ptrs स्टोर कर सकते हैं और यदि कोई अन्य साझा_पीआरआर उदाहरण नक्शे के भीतर ऑब्जेक्ट्स का संदर्भ नहीं देता है, वांछित के रूप में मानचित्र नष्ट होने पर ऑब्जेक्ट्स नष्ट हो जाएंगे।

2

यदि आप कच्चे पॉइंटर्स के बजाय smart pointers का उपयोग करते हैं, तो सब कुछ आपके लिए स्वचालित रूप से साफ हो जाएगा।

// header: 
using MapType = std::map<std::string, std::shared_ptr<MyType>>; 
shared_ptr<MapType> my_map; 

// usage: 
my_map.emplace("foo", std::make_shared<MyType>()); 

// destructor: 
MyClass::~MyClass() 
{ 
    // nothing! 
} 
3

इस संकेत दिए गए मानचित्र में निहित नष्ट करेगा [...]?

नहीं, आपके द्वारा प्रदान किए गए कोड को देखते हुए, आप मानचित्र के प्रत्येक सदस्य को रिसाव करेंगे।

एक नियम के रूप में, प्रत्येक new के लिए delete मिलान होना चाहिए। मानचित्र के लिए आपके पास delete है, लेकिन इसमें तत्वों के लिए कोई भी नहीं है।

इस समस्या का सबसे सही समाधान गतिशील आवंटन का उपयोग नहीं करना है। बस, MyType रों निर्देशिका की दुकान यदि संभव हो तो:

map<string,MyType> my_map; 

तो स्वत: भंडारण अवधि कुछ के लिए संभव नहीं है:

map<string, MyType>

... और बदले गतिशील कि स्वचालित रूप से map ही है, दुकान आवंटन की कारण, गतिशील आवंटन के लिए एक स्मार्ट सूचक का उपयोग करें। एक सी ++ 11 संकलक को देखते हुए, unique_ptr का उपयोग (या, शायद ही कभी, shared_ptr या यहाँ तक कि weak_ptr) map में तत्वों के लिए: (। एक सी ++ 03 संकलक को देखते हुए, उसके बूस्ट समकक्ष का उपयोग)

map<string, unique_ptr<MyType>> my_map; 

फिर जब my_map नष्ट हो जाता है, तो सभी तत्व delete डी होंगे।

बैरिंग यह सब, यदि आप एक स्थिति में हैं जहां से कोई भी ऊपर आप के लिए काम करेंगे (मैं अत्यधिक संदिग्ध से होगा), तो आप नक्शे अपने आप पुनरावृति करने की आवश्यकता होगी:

struct deleter 
{ 
    template <typename T> operator() (const T& rhs) const 
    { 
    delete rhs.second; 
    } 
}; 

for_each (my_map->begin(), my_map->end(), deleter()); 

में सी ++ 11, इस की रेखा के साथ एक लैम्ब्डा, कुछ किया जा सकता है:

for_each (my_map->begin(), my_map->end(), [](auto item) -> void 
{ 
    delete item.second; 
}); 
1

आधुनिक सी ++ में, बस अपने जीवन को आसान और उपयोग संकेत केवल बनाने अगर सख्ती से की आवश्यकता है।

आप इस कोड के साथ शुरू किया:

map<string, MyType *> *my_map = new map<string, MyType>; 

पहली बात आप कर सकते हैं, डेटा सदस्य के रूप में एक std::map उदाहरण का उपयोग करते हुए एक सूचक यह करने के बजाय विचार करना है। वास्तव में

// my_map data member - no pointers --> automatically deleted in class destructor 
map<string, MyType> my_map; 

आप हैं:

तो फिर, अगर MyType कॉपी करने के लिए सुपर महंगा नहीं है और इसकी उदाहरणों केवल मानचित्र के स्वामित्व में हैं, बस एक साधारण mapstring से MyType (MyType* के बजाय) के लिए विचार पॉइंटर्स वाले मानचित्र की आवश्यकता है, स्मार्ट पॉइंटर्स, std::shared_ptr (सी ++ 11/14 में उपलब्ध) साझा स्वामित्व के लिए, या std::unique_ptr अद्वितीय गैर-साझा स्वामित्व के लिए उपयोग करने पर विचार करें।
(। आप सी ++ 98/03 लक्षित करते हैं तो एक विकल्प boost::shared_ptr उपयोग करने के लिए है के बाद से कोई कदम अर्थ विज्ञान, आप unique_ptr, जो काफी हद तक इस कदम अर्थ विज्ञान की सुविधा पर आधारित है नहीं हो सकता।)
जैसे:

// Map containing _smart_ pointers 
//  --> default destructor is fine (no need for custom delete code) 
map<string, shared_ptr<MyType>> my_map; 

आप देख सकते हैं, मूल्य अर्थ विज्ञान (कच्चे संकेत के बजाय), या स्मार्ट संकेत का उपयोग कर, आप अपने कोड को सरल बनाने और स्वत: विनाश सी द्वारा ++ प्रदान की उपयोग कर सकते हैं।

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