2010-09-23 17 views
19

Próbuję usunąć zawartość wektora i pojawia się błąd - wektor iterator nie jest przyrostowy, dlaczego tak jest?Dlaczego ten wektor iteracyjny nie jest przyrostowy?

To mój destruktor:

City::~City() 
{ 
    vector <Base*>::iterator deleteIterator; 
    for (deleteIterator = m_basesVector.begin() ; deleteIterator != m_basesVector.end() ; deleteIterator++) 
     m_basesVector.erase(deleteIterator); 
} 

dzięki.

+5

Zakładając, że 'm_basesVector' jest członkiem' City', nie ma potrzeby usuwania jego elementów; jego destruktor wkrótce to zrobi. –

+3

Zdajesz sobie sprawę, że nie spowoduje to usunięcia obiektów, na które wskazują twoje wskaźniki. Aby to osiągnąć, musisz wywołać 'delete deleteIterator;' (jeśli tego chcesz). Jednak w tym przypadku powinieneś preferować 'boost :: ptr_vector'. –

+0

Zobacz [tam] (http://stackoverflow.com/questions/307082/). – Wok

Odpowiedz

41

erase unieważnia iterator. Nie możesz już z niego korzystać. Na szczęście dla ciebie, to zwraca iterator, które można użyć:

vector <Base*>::iterator deleteIterator = m_basesVector.begin(); 
while (deleteIterator != m_basesVector.end()) { 
    deleteIterator = m_basesVector.erase(deleteIterator); 
} 

czyli

m_basesVector.clear(); 

Czy jesteś odpowiedzialny za uwalniając pamięć określoną przez wskaźniki w wektorze? Jeśli to jest powód, dla którego robisz iterację (a twój prawdziwy program ma więcej kodu, którego nie pokazałeś, który uwalnia te obiekty w pętli), to pamiętaj, że kasowanie od początku wektora jest powolną operacją, ponieważ na każdym kroku wszystkie elementy wektora muszą być przesunięte w dół o jedno miejsce. Lepiej byłoby zapętlić wektor, uwalniając wszystko (potem clear() wektor, chociaż jak mówi Mike, nie jest to konieczne, jeśli wektor jest członkiem obiektu, który jest niszczony).

+0

+1 dla pierwszej pętli, wyczyść po. –

11

Problem polega na tym, że próbujesz użyć iteratora podczas używania funkcji erase(). erase(), push_back(), insert() i inne funkcje modyfikujące unieważniają iteratory w STL.

Wystarczy użyć jasnego() Funkcja:

City::~City() 
{ 
    m_basesVector.clear(); 
} 
+0

Cóż, niezależnie od tego, czy unieważnią iteratory, zależy od typu kontenera. – mkb

+0

@Matt, nie zależy to od używania wektorów. – riwalk

+1

@Matt: 'erase' zawsze unieważnia iteratory odnoszące się do wymazanego elementu. –

0

wektorowe iteratory są incrementable, ale jeśli usuniesz elementy, zawartość wektorowe są modyfikowane, a więc iterator jest nieprawidłowy.

Tak więc, jeśli usuniesz obiekty, powinieneś użyć wartości zwracanej erase(), która daje następny poprawny iterator.

1

Każdy iterator wskazujący usunięty element lub elementy po usuniętym zostaje unieważniony po wywołaniu metody usuwania wektora. Metoda Erase zwraca poprawny iterator wskazujący na następny element w wektorze. Powinieneś użyć tego iteratora, aby kontynuować zapętlenie & nie zwiększać unieważnionego iteratora. Możesz również użyć metody clear do usunięcia wszystkich elementów w wektorze. Należy jednak pamiętać, aby jawnie anulować przydzieloną pamięć dla elementów.

3

Jeśli próbuje uwolnić dane w wektorze, to zrobić:

for (std::vector<Base*>::iterator it = v.begin(), e = b.end(); it != e; ++it) 
    delete *it; 
1

Ten kod przecieki całą zawartość wektora - trzeba delete *deleteIterator w pętli też. Możesz tego uniknąć, używając Base zamiast Base* jako treści vector, a następnie clear() zniszczy je dla Ciebie. Lub użyj boost::ptr_vector, który automatyzuje zniszczenie, jeśli potrzebujesz surowych wskaźników.

Wywołanie w ten sposób pod numer erase() może być bardzo kosztowne, jeśli vector jest duże, ponieważ każdy element powyżej bieżącej pozycji musi zostać przesunięty w dół, aby zapewnić, że elementy będą przylegać. Unikaj ręcznego usuwania proponowanego typu, z tego i innych powodów.

2

Umieszczanie tego po prostu przysięga, że ​​ktoś inny ma ten problem i próbuje tego rozwiązania zastanawiać się, dlaczego nie działa tutaj, to faktyczne rozwiązanie/wyjaśnienie.

@Steve Jessop - Twój kod jest wadliwy i masz go również tutaj napisane ... (Ja również zredagowałem jego wpis, aby naprawić problem, jak tylko zostanie zatwierdzony, zostanie naprawiony w oryginalnym wpisie)

http://techsoftcomputing.com/faq/3779252.html

nie widzę w jaki sposób jest to „rozwiązanie” problemu, kiedy utworzyć nową emisję poprzez nieskończoną pętlę powinna istnieć deleteIterator ++ wewnątrz pętli while tak, że rzeczywiście osiągnie koniec wektora.

Też wpadłem na ten problem, a moje rozwiązanie znajdowało się wewnątrz pętli while, sprawdzając, czy iterator był równy końcowi, czy rozmiar wektorowy miał wartość 0 i zrywał przed próbą inkrementacji iteratora.

Przykł.

std::vector<RankPlayer*>::iterator Rank_IT = CurrentPlayers.begin(); 

    while (Rank_IT != CurrentPlayers.end()) 
    {  
     RankPlayer* SelPlayer = (*Rank_IT); 

     if(strstr(SelPlayer->GamerTag, this->GamerTag) != NULL) 
     { 

      delete[] SelPlayer->PlayerData; 
      delete[] SelPlayer; 
      Rank_IT = CurrentPlayers.erase(Rank_IT); 
     } 

     if(Rank_IT == CurrentPlayers.end() || CurrentPlayers.size() == 0) 
     { 
      break; 
     } 
      ++Rank_IT; 
    } 
+0

To jest odpowiedź i rant, a także komentarz.Zdecydowanie sugeruję, aby było mniej rantu i komentarza, lub zostanie szybko usunięty. –

2

Nie dotyczy to pierwotnego problemu zamieszczonego powyżej, ale wyszukiwanie tego błędu przez Google prowadzi mnie do tej strony, więc zamieszczam ją tutaj, aby każdy mógł ją zobaczyć.

Wpadłem ostatnio na ten komunikat o błędzie i sprawdziłem wszystkie linie kodów (nie było "wymazywania" ani niczego podobnego, wektor był tylko czytany).

W końcu zdałem sobie sprawę, że istnieje problem z zagnieżdżonymi pętlami.

Rozważmy na przykład coś takiego: - (!)

`for (it=begin(); it!=end();i++) 
{ 
    for (; it!=end();i++) 
    { 
    } 
}` 

Kiedy skończysz z zagnieżdżonej pętli, to zwiększa zawartość iterator, a następnie, pętla rodzic go inkrementować ponownie, ostatecznie czyni krok iteratora nad końcem(). To znaczy. byłoby to "end() + 1", gdyby coś takiego było. W konsekwencji pętla nadrzędna zgłasza ten błąd przy następnym sprawdzaniu.

Aby obejść ten problem, skończyło się wstawić ten wiersz po pętli dziecka:

`if (it == vStringList.end()) --it;` 

Brudne, ale działa: D

Wiem, że może to być oczywiste dla niektórych, ale mam przez chwilę nad tym głowiłem, lol

Powiązane problemy