2013-02-23 3 views
1

У меня есть карта, какие элементы vectors.I должны удалить из этих векторов всех элементов, которые равны специального номер numвектора итераторы несовместим, а вычеркнуть из вектора

std::map<size_t,std::vector<size_t> > myMap; 
for (std::map<size_t,std::vector<size_t> >::iterator itMap = myMap.begin();itMap != myMap.end();++itMap) 
{ 
    for (std::vector<size_t>::iterator itVec = itMap->second.begin();itVec != itMap->second.end();) 
    { 
     auto itNextVec = itVec; 
     ++itNextVec; 
     if (*itVec == num) 
     { 
      itMap->second.erase(itVec); 
     } 
     itVec = itNextVec; 
    } 
} 

Код причина время выполнения exepssion. В VS - vector iterators incompatible. Может кто-нибудь указать, в чем причина?

Благодаря

+0

Вы знаете о ['std :: remove'] (http://en.cppreference.com/w/cpp/algorithm/remove), правильно? Это будет не только красивее, но и более эффективно. 'auto & v = itMap-> second; v.erase (std :: remove (v.begin(), v.end(), num), v.end()); ' –

ответ

6

std::vector::erase возвращает iterator в следующую позицию списка, поэтому при стирании вы должны сделать свой итератор равным возвращаемому значению.

Единственное, что вы должны учитывать, это то, что возвращаемый iterator может быть концом, поэтому вы должны это проверить.

То, что я лично хотел бы сделать это после делать в стирают, и я получаю следующую позицию итератора, я возвращаюсь в прежнее положение возвращенного итератора и чем называть по-прежнему на примере for loop

:

#include <vector> 
#include <iostream> 

int main() 
{ 
    std::vector<int> myInt; 
    myInt.push_back(1);myInt.push_back(2);myInt.push_back(3); 

    for(auto iter = myInt.begin(); 
     iter != myInt.end(); 
     ++iter) 
    { 
     if(*iter == 1) 
     { 
      iter = myInt.erase(iter); 
      if(iter != myInt.begin()) 
      { 
       iter = std::prev(iter); 
       continue; 
      } 
     } 

     std::cout << *iter << std::endl; 
    } 
} 

Но делать стирающий внутри цикла итератора неодобрение, потому что он аннулирует старый итератор, и это может вызвать много проблем, если вы не планировали для них.

+0

Можете ли вы объяснить мне, почему мой подход не очень хорош: я не обращаюсь или не увеличиваю его после удаления, но использую auto itNextVec для его обновления – Yakov

+4

@Yakov: 'erase' не только отменяет итератор, на который он был вызван, он аннулирует каждый итератор, который указывает на позицию после него. –

+0

@BenjaminLindley - только в векторе или в каждом контейнере std? – Yakov

1

Вы не можете тривиальным стирают элемент из коллекции в то время как итерация над ним. Подумайте немного об этом, вы удалите то, что itVec «указывает» на, после удаления itVec больше не «указывает» на элемент, поэтому он больше не имеет «следующего» указателя.

Если вы проверяете, например, this reference, вы увидите, что функция erase возвращает итератор в следующий элемент. Продолжайте цикл с этим (без увеличения его, конечно).

+0

Но по этой причине я сохраняю auto itNextVec – Yakov

2

стирание аннулирует Итератор

Iterator validity 
Iterators, pointers and references pointing to position (or first) and beyond are 
invalidated, with all iterators, pointers and references to elements before position (or 
first) are guaranteed to keep referring to the same elements they were referring to 
before the call. 
1

Рассмотрит либо с использованием другого класса коллекции, чем vector или создать новый вектор с желаемыми элементами удалены, а не удаление из существующего вектора.

+0

Можете ли вы сказать мне, почему auto itNextVec doesn Решить это? – Yakov

Смежные вопросы