向量迭代器与向量擦除时不兼容

时间:2013-02-23 16:47:05

标签: c++ map vector iterator erase

我有一个地图,其中的元素是向量。我必须从这些向量中删除所有等于特殊数字的元素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中。 有人能说出原因是什么吗?

由于

4 个答案:

答案 0 :(得分:6)

std::vector::eraseiterator返回到列表的下一个位置,因此当您执行擦除时,应使迭代器等于返回的值。

您唯一需要考虑的是返回的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;
    }
}

但是在迭代器循环内部进行擦除是不受欢迎的,因为它使旧迭代器无效,如果你没有计划它们,可能会导致很多问题。

答案 1 :(得分: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.

答案 2 :(得分:1)

在迭代它时,你不能轻易地擦除集合中的项目。稍微考虑一下,删除itVec“指向”的内容,删除后itVec不再“指向”某个元素,因此它不再具有“下一个”指针。

如果你检查,例如this reference,您将看到erase函数返回下一个元素的迭代器。用这个继续循环(当然不增加它)。

答案 3 :(得分:1)

考虑使用与vector不同的集合类,或者创建一个删除了所需项目的新向量,而不是从现有向量中删除。