У меня есть карта, элементы которой являются векторами. Я должен удалить из этих векторов все элементы, которые равны специальному числу 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;
}
}
Код вызывает исключение во время выполнения. В VS — vector iterators incompatible
,
Может кто-то указать, что является причиной этого?
Спасибо
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;
}
}
Но стирание внутри цикла итератора не одобряется, потому что оно делает недействительным старый итератор, и это может вызвать много проблем, если вы не планируете их.
стирание сделает недействительным итератор
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.
Вы не можете тривиально удалить элемент из коллекции, перебирая его. Подумайте немного об этом, ваше удаление, что itVec
«указывает», после удаления itVec
больше не «указывает» на элемент, поэтому у него больше нет указателя «следующий».
Если вы проверите, например, эта ссылка, вы увидите, что erase
Функция возвращает итератор для следующего элемента. Продолжайте цикл с этим (не увеличивая его, конечно).
Рассмотрите возможность использования другого класса коллекции, чем vector
или создание нового вектора с удалением нужных элементов вместо удаления из существующего вектора.