मुझे एक सेट के माध्यम से जाने और पूर्वनिर्धारित मानदंडों को पूरा करने वाले तत्वों को हटाने की आवश्यकता है।
यह मेरे द्वारा लिखा गया परीक्षण कोड है:
#include <set>
#include <algorithm>
void printElement(int value) {
std::cout << value << " ";
}
int main() {
int initNum[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::set<int> numbers(initNum, initNum + 10);
// print '0 1 2 3 4 5 6 7 8 9'
std::for_each(numbers.begin(), numbers.end(), printElement);
std::set<int>::iterator it = numbers.begin();
// iterate through the set and erase all even numbers
for (; it != numbers.end(); ++it) {
int n = *it;
if (n % 2 == 0) {
// wouldn't invalidate the iterator?
numbers.erase(it);
}
}
// print '1 3 5 7 9'
std::for_each(numbers.begin(), numbers.end(), printElement);
return 0;
}
सबसे पहले, मैंने सोचा था कि सेट से एक तत्व को मिटाते समय इसके माध्यम से पुनरावृत्ति करना पुनरावृत्ति को अमान्य कर देगा, और लूप के लिए वेतन वृद्धि अपरिभाषित व्यवहार होगा। हालांकि, मैंने इस परीक्षण कोड को निष्पादित किया और सभी अच्छी तरह से चले गए, और मैं समझा नहीं सकता कि क्यों।
मेरा प्रश्न: क्या यह एसटीडी सेट के लिए परिभाषित व्यवहार है या यह कार्यान्वयन विशिष्ट है? मैं ubuntu 10.04 (32-बिट संस्करण) पर gcc 4.3.3 का उपयोग कर रहा हूं, वैसे।
धन्यवाद!
प्रस्तावित समाधान:
क्या यह सेट से तत्वों को पुनरावृत्त और मिटाने का एक सही तरीका है?
while(it != numbers.end()) {
int n = *it;
if (n % 2 == 0) {
// post-increment operator returns a copy, then increment
numbers.erase(it++);
} else {
// pre-increment operator increments, then return
++it;
}
}
संपादित करें: पूर्वनिर्धारित समाधान
मैं एक समाधान के आसपास आया था जो मुझे अधिक सुरुचिपूर्ण लगता है, भले ही यह बिल्कुल वैसा ही हो।
while(it != numbers.end()) {
// copy the current iterator then increment it
std::set<int>::iterator current = it++;
int n = *current;
if (n % 2 == 0) {
// don't invalidate iterator it, because it is already
// pointing to the next element
numbers.erase(current);
}
}
यदि कुछ समय के भीतर कई परीक्षण स्थितियां हैं, तो उनमें से प्रत्येक को पुनरावृत्ति बढ़ाना चाहिए। मुझे यह कोड बेहतर पसंद है क्योंकि यह इटरेटर केवल एक ही स्थान पर बढ़ा हुआ है , जिससे कोड कम त्रुटि-प्रवण और अधिक पठनीय हो जाता है।
++it
तुलना में कुछ अधिक कुशल होना चाहिए it++
क्योंकि इसे पुनरावृत्त की एक अदृश्य अस्थायी प्रतिलिपि के उपयोग की आवश्यकता नहीं है। कॉर्नेल का संस्करण अब सुनिश्चित करता है कि गैर-फ़िल्टर किए गए तत्व सबसे अधिक कुशलता से पुन: प्रसारित होते हैं।