2010-03-17 15 views
7

मान लीजिए मेरे पास एक एसटीएल मानचित्र है जहां मान पॉइंटर्स हैं, और मैं उन्हें सभी को हटाना चाहता हूं। मैं निम्नलिखित कोड का प्रतिनिधित्व कैसे करूं, लेकिन std :: for_each का उपयोग कर रहा हूं? बूस्ट का उपयोग करने के लिए समाधान के लिए मैं खुश हूं।मैं एसटीएल मानचित्र में प्रत्येक मान को हटाने के लिए for_each का उपयोग कैसे करूं?

for(stdext::hash_map<int, Foo *>::iterator ir = myMap.begin(); 
    ir != myMap.end(); 
    ++ir) 
{ 
    delete ir->second; // delete all the (Foo *) values. 
} 

(मैं बूस्ट के checked_delete पाया है, लेकिन मुझे यकीन है कि कैसे pair<int, Foo *> कि इटरेटर का प्रतिनिधित्व करता है कि लागू करने के लिए नहीं कर रहा हूँ)।

(इसके अलावा, इस प्रश्न के प्रयोजनों के लिए, इस तथ्य को अनदेखा करें कि एक एसटीएल कंटेनर में हटाने की आवश्यकता वाले कच्चे पॉइंटर्स को संग्रहीत करना बहुत समझदार नहीं है)।

नोट: मैंने बाद में एक पंक्ति का उत्तर पाया और सूचीबद्ध किया है ... लेकिन कोड बहुत भयानक है इसलिए मैंने जीएमएन के स्वीयर जवाब को स्वीकार कर लिया है।

struct second_deleter 
{ 
    template <typename T> 
    void operator()(const T& pX) const 
    { 
     delete pX.second; 
    } 
}; 

std::for_each(myMap.begin(), myMap.end(), second_deleter()); 

आप को बढ़ावा देने का उपयोग कर रहे हैं, तो आप भी लैम्ब्डा पुस्तकालय इस्तेमाल कर सकते हैं:

+0

आपके पुनरावर्तक पर प्रीइंक्रमेंट ऑपरेशन का अच्छा उपयोग! –

उत्तर

14

आप एक समारोह वस्तु बनाना है

namespace bl = boost::lambda; 
std::for_each(myMap.begin(), myMap.end(), second_deleter(), 
       bl::bind(bl::delete_ptr(), 
       bl::bind(std::select2nd<myMap::value_type>(), _1)); 

लेकिन आप pointer containers पुस्तकालय की कोशिश हो सकता है यह स्वचालित रूप से करता है।

ध्यान दें कि आप मानचित्र का उपयोग नहीं कर रहे हैं, लेकिन hash_map। मैं आपको बूस्ट unordered_map पर स्विच करने की सलाह देता हूं, जो अधिक वर्तमान है। हालांकि, ptr_unordered_map प्रतीत नहीं होता है।

सुरक्षा के लिए, आपको यह चीज़ लपेटनी चाहिए। उदाहरण के लिए:

template <typename T, typename Deleter> 
struct wrapped_container 
{ 
    typedef T container_type; 
    typedef Deleter deleter_type; 

    wrapped_container(const T& pContainer) : 
    container(pContainer) 
    {} 

    ~wrapped_container(void) 
    { 
     std::for_each(container.begin(), container.end(), deleter_type()); 
    } 

    T container; 
}; 

और का उपयोग यह पसंद:

typedef wrapped_container< 
      boost::unordered_map<int, Foo*>, second_deleter> my_container; 

my_container.container./* ... */ 

यह कोई बात नहीं क्या, अपने कंटेनर एक Deleter साथ के माध्यम से दोहराया हो जाएगा सुनिश्चित करता है। (। अपवाद, उदाहरण के लिए के लिए)

की तुलना करें:

std::vector<int*> v; 
v.push_back(new int); 

throw "leaks!"; // nothing in vector is deleted 

wrapped_container<std::vector<int*> > v; 
v.container.push_back(new int); 

throw "no leaks!"; // wrapped_container destructs, deletes elements 
+0

मुझे लगा कि यह ऐसा कुछ हो सकता है। मैंने आशा की थी कि यह मेरे अपने प्रकार को परिभाषित किए बिना ऐसा करना संभव होगा। क्या बूस्ट :: बाइंड या select2nd या somesuch का उपयोग करना संभव है, मुझे आश्चर्य है? – stusmith

+0

क्या यह तकनीकी रूप से यूबी का आह्वान नहीं करता है यदि नक्शा स्वयं को फिर से संतुलित करने का निर्णय लेता है और इस प्रकार हटाए गए पॉइंटर्स को प्रतिलिपि बनाना शुरू कर देता है? शायद उन्हें भी कम कर सकते हैं? - बस देखा है कि यह हैश_मैप नक्शा नहीं है, इसलिए यह –

+0

@jk को फिर से संतुलित नहीं करेगा: यह मानचित्र से कुछ भी नहीं हटा रहा है, केवल उन वस्तुओं को हटा रहा है जो यह इंगित करता है। –

0

तो यह संभव है, यही कारण है कि आप स्मार्ट संकेत दिए गए अपने नक्शे में उपयोग नहीं करते हैं?

+0

किसी बिंदु पर यह संभव होना चाहिए। मैं फिलहाल कुछ पुराने कोड को दोबारा कर रहा हूं। सच में, मैं सिर्फ उत्सुक था कि मैं इसे कोड की एक पंक्ति में कर सकता हूं या नहीं। लेकिन आप बिल्कुल सही हैं, अंत में मैं वहां जाना चाहता हूं ... लेकिन यह 15 साल के पुराने कोड की दस लाख लाइनों का हिस्सा है। – stusmith

+0

मैं आपका पॉइंट देखता हूं, लेकिन यहां स्मार्ट पॉइंटर्स का उपयोग सदस्य हटाने को डीबग करने और डीबग करने की आवश्यकता को हटा देता है। आगे जाने के बारे में चिंता करने के लिए एक कम स्मृति प्रबंधन। जब भी मैं नई/डिलीट का उपयोग करता हूं, मुझे लगता है कि इसकी आवश्यकता है या नहीं। यदि आप चाहें तो व्यक्तिगत "कोड गंध" (प्रति मार्टिन फाउलर)। –

+0

बेशक, यदि आपका पुराना कोड मानचित्र लौटाता है, तो 'for_each' दृष्टिकोण शायद आपकी सबसे अच्छी शर्त है - लेकिन यदि आपके पास मानचित्र बनाने में कुछ हाथ था, तो मैं स्मार्ट पॉइंटर्स का उपयोग करने की सलाह दूंगा। – Jacob

3

क्या आपने BOOST_FOREACH का उपयोग करने का प्रयास किया है? इससे आपको अपना खुद का मज़ेदार बनाये बिना लाइन में ऐसा करने की अनुमति मिलनी चाहिए।

मैं (यदि वास्तव में नहीं) निम्नलिखित कोड का परीक्षण किया है, लेकिन यह कुछ इस तरह दिखना चाहिए:

typedef stdext::hash_map<int, Foo *> MyMapType; //see comment. 
BOOST_FOREACH(MyMapType::value_type& p, myMap) 
{ 
    delete p.second; 
} 

खैर 1 से अधिक लाइन thats, typedef :) ठीक की वजह से

+0

आम तौर पर ध्वनि। दुर्भाग्यवश, यह एक मैक्रो है और '<> ' – UncleBens

+1

आह हाँ के बीच कॉमा को संभाल नहीं सकता है, एक टाइपिफ़ की आवश्यकता होगी, इसके बारे में खेद है, अब एक पंक्ति नहीं है। – Akanksh

0

, मैंने पाया कि इसे एक पंक्ति में कैसे करना है ... लेकिन मुझे नहीं लगता कि मैं वास्तव में असली कोड में निम्नलिखित करता हूं!

std::for_each(mayMap.begin() 
      , myMap.end() 
      , boost::bind(&boost::checked_delete<Foo> 
          , boost::bind(&stdext::hash_map<int, Foo *>::value_type::second, _1))); 

हालांकि मैं क्योंकि मैं एक लिपटे कंटेनर के अपने विचार हैं, और मेरे जवाब की तरह, के रूप में अनुरोध एक लाइन होने के बावजूद GMAN के जवाब को स्वीकार करने के लिए जा रहा हूँ, बस सादा बुरा है।

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

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