Saya perlu melalui satu set dan menghapus elemen yang memenuhi kriteria yang telah ditentukan.
Ini adalah kode tes yang saya tulis:
#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;
}
Pada awalnya, saya berpikir bahwa menghapus elemen dari set sementara iterasi melalui itu akan membatalkan iterator, dan kenaikan pada for loop akan memiliki perilaku yang tidak terdefinisi. Meskipun demikian, saya menjalankan kode tes ini dan semuanya berjalan dengan baik, dan saya tidak bisa menjelaskan mengapa.
Pertanyaan saya: Apakah ini perilaku yang ditentukan untuk set std atau apakah implementasi ini spesifik? Saya menggunakan gcc 4.3.3 di ubuntu 10.04 (versi 32-bit), omong-omong.
Terima kasih!
Solusi yang diusulkan:
Apakah ini cara yang benar untuk mengulang dan menghapus elemen dari set?
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;
}
}
Sunting: SOLUSI YANG DITENTUKAN
Saya menemukan solusi yang tampaknya lebih elegan bagi saya, meskipun tidak persis sama.
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);
}
}
Jika ada beberapa kondisi pengujian di dalam sementara, masing-masing harus meningkatkan iterator. Saya lebih suka kode ini karena iterator hanya bertambah di satu tempat , membuat kode lebih sedikit rawan kesalahan dan lebih mudah dibaca.
++it
seharusnya lebih efisien daripada it++
karena tidak memerlukan penggunaan salinan sementara iterator yang tidak terlihat. Versi Kornel sementara lebih lama memastikan bahwa elemen-elemen yang tidak disaring diulang dengan lebih efisien.