SORU
20 Mayıs 2010, PERŞEMBE


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
20 Mayıs 2010, PERŞEMBE


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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Jabari Johnson

    Jabari Johns

    18 Ocak 2008
  • psidot

    psidot

    2 Kasım 2006
  • The Pet Collective

    The Pet Coll

    5 Ocak 2012