STL silme öğeleri yineleme sırasında set
Bir dizi geçmesi ve önceden tanımlanmış ölçütlere uyan öğeleri kaldırmak için ihtiyacım var.
Bu yazdığım test kodu:
#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;
}
İlk başta, bu yineleme sırasında kümesinden bir öğe silme yineleyici geçersiz olacağını düşündüm, ve döngü için de artış tanımsız davranış olurdu. Olsa bile, bu test kodu uyguladım ve her şey iyi gitti, ve neden açıklayamam.
Sorum şu: Bu std kümesi için tanımlanan davranış, ya da bu uygulama belirli mi? Bu arada ubuntu 10.04 (32-bit sürüm), gcc 4.3.3 kullanıyorum.
Teşekkürler!
Çözüm önerdi:
Bu doğru bir şekilde ayarlayın öğeleri yineleme silmek mi?
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;
}
}
Edit: TERCİH edilen ÇÖZÜM
Aynen öyle olsa benim için çok daha şık görünen bir çözüm geldim.
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);
}
}
Eğer bu süre içinde birkaç test koşulları varsa, bunların her biri yineleyici artırmak gerekir. Yineleyici artırılır çünkü bu kod daha çok seviyorumbir yerde sadecekodu daha az hata eğilimli ve daha okunabilir yapmak.
CEVAP
Bu uygulamaya bağlıdır:
Standart 23.1.2.8:
Ekle üye konteyner kullanımına ve başvurular geçerliliğini etkilemez ve üyeler silinmiş öğeleri yalnızca kullanımına ve başvurular geçersiz olacaktır silme.
Belki standarttır bu çok uygun deneyebilirsiniz:
for (it = numbers.begin(); it != numbers.end(); ) {
if (*it % 2 == 0) {
numbers.erase(it );
}
else {
it;
}
}
Silmek için eski pozisyonuna geçer, bu yüzden postfix, ama önce bir yeni bir operatöre bağlı atlar unutmayın.
Python yineleme sırasında bir listeden...
Nasıl üzerinde yineleme sırasında gene...
Bir std öğeleri kaldırın::bu yineleme ...
Nasıl üzerinde yineleme sırasında bir ...
Neden TextBox ekleme yapar.Bir döngü s...