从矢量中擦除时矢量迭代器不兼容

vector iterators incompatible while erase from vector

本文关键字:迭代器 不兼容 擦除      更新时间:2023-10-16

我有一个元素是向量的映射。我必须从这些向量中删除所有等于特殊数字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 上调用continue

示例:

#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的集合类,或者创建一个新的向量,删除所需的项,而不是从现有向量中删除。