2011-06-23 9 views
12
int main() 
{ 

     const int SIZE = 10; 
     int a[SIZE] = {10, 2, 35, 5, 10, 26, 67, 2, 5, 10}; 
     std::ostream_iterator<int> output(cout, " "); 
     std::vector<int> v(a, a + SIZE); 
     std::vector<int>::iterator newLastElement; 

     cout << "contents of the vector: "; 
     std::copy(v.begin(), v.end(), output); 

     newLastElement = std::remove(v.begin(), v.end(), 10); 
     cout << "\ncontents of the vector after remove: "; 
     //std::copy(v.begin(), newLastElement, output); 
         //this gives the correct result : 2 35 5 26 67 2 5 
     std::copy(v.begin(), v.end(), output); 
      //this gives a 10 which was supposed to be removed : 2 35 5 26 67 2 5 2 5 10 

     cout << endl; 
     return 0; 
} 

सरणी में तीन 10 हैं।एसटीएल हटाने की उम्मीद के रूप में काम नहीं करता है?

हटाए गए फ़ंक्शन के साथ सभी 10s को हटाने के बाद सरणी v में 10 क्यों शामिल हैं।

आप संकलित उत्पादन देख सकते हैं भी here

+0

वैसे, यह टिप्पणी है ('// यह सही परिणाम देता है: 2 35 5 26 67 2 5 2 5') प्रोग्राम वास्तव में क्या उत्सर्जित करता है? आप वास्तव में '2 35 5 26 67 2 5' कहना चाहते थे, है ना? –

+0

हां, बिल्कुल सही। – munish

उत्तर

26

असल में std::remove कंटेनर से आइटम को नहीं हटाता है। से here

निकालें उद्धरित रेंज [first, last) सभी तत्वों value के बराबर हैं से निकाल देता है। यही है, रिटर्न को एक इटरेटर new_last रिटर्न हटा दें जैसे [first, new_last) में value के बराबर कोई तत्व नहीं है। [new_last, last) श्रेणी में पुनरावृत्त सभी अभी भी भरोसेमंद हैं, लेकिन वे तत्व जो वे इंगित करते हैं निर्दिष्ट हैं। निकालें स्थिर है, जिसका अर्थ है कि तत्वों कि मूल्य के बराबर नहीं हैं के रिश्तेदार आदेश unchanged.`

है, std::remove काम करता है केवल iterators की एक जोड़ी के साथ है और कंटेनर जो वास्तव में होता है के बारे में कुछ भी पता नहीं है सामान। वास्तव में, अंतर्निहित कंटेनर को जानने के लिए std::remove के लिए यह संभव नहीं है, क्योंकि इटरेटर की एक जोड़ी से यह पता लगाने के लिए कोई तरीका नहीं है कि यह कंटेनर के बारे में पता लगाने के लिए जहां इटरेटर संबंधित हैं। तो std::remove वास्तव में आइटम को हटा नहीं देता है, बस क्योंकि यह नहीं कर सकता है। वास्तव में एकमात्र तरीका कंटेनर से किसी आइटम को निकालने के लिए उस कंटेनर पर सदस्य फ़ंक्शन का आह्वान करना है।

तो अगर आप आइटम हटाने के लिए चाहते हैं, तो Erase-Remove Idiom का उपयोग करें:

v.erase(std::remove(v.begin(), v.end(), 10), v.end()); 

erase-remove idiom इतना आम है और उपयोगी है कि std::listlist::remove नामक एक और सदस्य समारोह जो रूप में एक ही प्रभाव पैदा जोड़ा गया है है erase-remove मुहावरे की है।

std::list<int> l; 
//... 
l.remove(10); //it "actually" removes all elements with value 10! 

इसका मतलब है, आप erase-remove मुहावरा उपयोग करने के लिए जब आप std::list के साथ काम नहीं करना है। आप सीधे अपने सदस्य फ़ंक्शन list::remove पर कॉल कर सकते हैं।

+1

ऐसा लगता है कि 'cplusplus.com' को सभी परिभाषाओं को सही किया गया है, कृपया अपना उत्तर देखें और संपादित करें क्योंकि यह उस साइट के बारे में नकारात्मक अभिविन्यास बनाता है। –

11

कारण यह है कि एसटीएल एल्गोरिदम अनुक्रम के आकार को संशोधित नहीं है। remove, वास्तव में वस्तुओं को मिटाने के बजाय, उन्हें स्थानांतरित करता है और "नया" अंत में एक पुनरावर्तक लौटाता है। यही कारण है कि इटरेटर तो अपने कंटेनर के erase सदस्य समारोह के लिए पारित किया जा सकता है वास्तव में हटाने प्रदर्शन करने के लिए:

v.erase(std::remove(v.begin(), v.end(), 10), v.end()); 

वैसे, इस "मिटा-हटाने मुहावरा" के रूप में जाना जाता है।

संपादित करें: मैं गलत था। टिप्पणियां, और नवाज का जवाब देखें।

+0

+1 move_to_end() को इंगित करने के लिए धन्यवाद मेरे लिए फिट होगा। – Simone

+3

[नवाज़] (http://stackoverflow.com/questions/6456870/stl-remove-function/6456967#6456967) का उत्तर कहता है कि नए छोर के पीछे के तत्व अनिर्दिष्ट हैं और आवश्यक तत्वों के बराबर नहीं हैं, इसलिए आप एक विशेष कार्यान्वयन का एक आर्टिफैक्ट देख रहे हैं। समारोह का नाम बदलना उचित नहीं होगा। –

+0

@ मार्क दिलचस्प। –

1

क्योंकि std::remove वास्तव में कंटेनर को कम नहीं करता है, यह केवल "हटाए गए" तत्व द्वारा उपयोग की जाने वाली जगह को भरने के लिए सभी तत्वों को नीचे ले जाता है। उदाहरण के लिए, यदि आपके पास 1 2 3 4 5 अनुक्रम है और का उपयोग 2 मानने के लिए करें, तो आपका अनुक्रम 1 3 4 5 5 जैसा दिखेगा। यदि आप मान 4 हटाते हैं, तो आपको 1 3 5 5 5 मिल जाएगा। किसी भी समय अनुक्रम को कम होने के लिए कहा जाता है।

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