क्या std :: निकाल क्या करता है?
यहां std::remove
का छद्म कोड है। यह देखने के लिए कुछ सेकंड लें कि इसके क्या कर रहे हैं और फिर स्पष्टीकरण पढ़ें।
Iter remove(Iter start, Iter end, T val) {
Iter destination = start;
//loop through entire list
while(start != end) {
//skip element(s) to be removed
if (*start == val) {
start++;
}
else //retain rest of the elements
*destination++ = *start++;
}
//return the new end of the list
return destination;
}
सूचना है कि हटाने बस अनुक्रम में तत्वों ऊपर ले जाया गया, मूल्यों, जिसे आप निकालना चाहते थे अधिलेखित। तो जो मूल्य आप निकालना चाहते थे वे वास्तव में चले गए हैं, लेकिन फिर समस्या क्या है? मान लें कि आपके पास मूल्य {1, 2, 3, 4, 5} के साथ वेक्टर था। वैल = 3 के लिए निकालने के बाद, वेक्टर में अब {1, 2, 4, 5, 5} है। यही कारण है कि 4 और 5 ऊपर ले जाया गया ताकि 3 वेक्टर लेकिन वेक्टर के आकार नहीं बदला है से चला गया है, है। इसके अलावा, वेक्टर के अंत अब 5.
की प्रति के साथ इसमें अतिरिक्त बाईं वेक्टर :: मिटा क्या करता है शामिल हैं?
std::erase
उस श्रेणी की शुरुआत और समाप्ति लेता है जिसे आप छुटकारा पाने के लिए चाहते हैं।यह मान नहीं लेता है, जिसे आप निकालना चाहते हैं, केवल श्रेणी के प्रारंभ और समाप्ति को हटाना चाहते हैं। यह ऐसे काम करता लिए छद्म कोड है:
erase(Iter first, Iter last)
{
//copy remaining elements from last
while (last != end())
*first++ = *last++;
//truncate vector
resize(first - begin());
}
तो मिटा आपरेशन वास्तव में कंटेनर के आकार बदलता है और इसलिए स्मृति मिल जाता है।
निकालें-मिटा मुहावरा
std::remove
और std::erase
के संयोजन आप इतना है कि कंटेनर वास्तव में काट होगा अगर तत्वों को हटा दिया गया कंटेनर से मिलान तत्वों को दूर करने के लिए अनुमति देता है। यहां बताया गया है कि यह कैसे करें:
//first do the remove
auto removed = std::remove(vec.begin(), vec.end(), val);
//now truncate the vector
vec.erase(removed, vec.end());
इसे हटाने-मिटाए गए मुहावरे के रूप में जाना जाता है। यह इस तरह क्यों डिजाइन किया गया है? अंतर्दृष्टि यह है कि तत्वों को खोजने का संचालन अधिक सामान्य और अंतर्निहित कंटेनर से स्वतंत्र है (केवल इटरेटर पर निर्भर)। हालांकि मिटाने का संचालन इस बात पर निर्भर करता है कि कैसे कंटेनर मेमोरी संग्रहीत कर रहा है (उदाहरण के लिए, हो सकता है कि आपने गतिशील सरणी के बजाय लिंक लिंक्ड हो)। इसलिए एसटीएल जेनेरिक "हटाने" ऑपरेशन प्रदान करते समय कंटेनरों को अपना खुद का मिटाने की अपेक्षा करता है ताकि सभी कंटेनरों को उस कोड को लागू करने की आवश्यकता न हो। मेरे विचार में, नाम बहुत भ्रामक है और std::remove
को std::find_move
कहा जाना चाहिए था।
नोट: ऊपर कोड सख्ती से स्यूडोकोड है। वास्तविक एसटीएल कार्यान्वयन अधिक स्मार्ट है, उदाहरण के लिए, प्रतिलिपि के बजाय std::move
का उपयोग करना।
मुझे लगता है इस बारे में सबसे कठिन हिस्सा मिटा सकते हैं और हटाने का मतलब लगभग अंग्रेजी में बात बचाने के है, इसलिए इसकी आसान जो एक जो –