为什么这个向量迭代器不可递增?

时间:2010-09-23 14:09:17

标签: c++ memory-management vector iterator

我正在尝试删除向量的内容而我收到错误 - 向量迭代器不可递增,为什么会这样?

这是我的析构函数:

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

感谢。

8 个答案:

答案 0 :(得分:44)

erase使迭代器无效。你不能再使用它了。幸运的是,它返回一个你可以使用的迭代器:

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

或者:

m_basesVector.clear();

你是否有责任释放向量中指针引用的内存?如果这就是你正在迭代的原因(并且你的真实程序有更多你没有显示的代码,那就是释放循环中的那些对象),那么请记住,从向量的开头擦除是一个缓慢的操作,因为在每一步中,矢量的所有元素都必须向下移动一个位置。更好的是循环向量释放所有东西(然后clear()向量,尽管迈克说如果向量是被破坏的对象的成员则没有必要。

答案 1 :(得分:11)

问题是您在使用erase()函数时尝试使用迭代器。 erase(),push_back(),insert()和其他修改函数使STL中的迭代器无效。

只需使用clear()函数:

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

答案 2 :(得分:3)

如果您尝试释放向量中的数据,请执行以下操作:

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

答案 3 :(得分:2)

发布这个只是因为其他人有这个问题,并尝试这个解决方案,想知道为什么它不能在这里工作是一个实际的解决方案/解释。

@Steve Jessop - 你的代码存在缺陷,你也在这里写了......(我也编辑了他的帖子,一旦它被批准就修复了它,它将在原帖中修复)

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

我不知道这是一个问题的“解决方案”,当它通过无限循环创建一个新问题时,while循环中应该有一个deleteIterator ++,以便它实际到达向量的末尾。 / p>

此外我遇到了这个问题,我的解决方案是在while循环中检查迭代器是否等于结尾,或者如果向量大小为0并且在尝试递增迭代器之前断开了。

实施例

    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;
    }

答案 4 :(得分:2)

这与上面发布的原始问题无关,但Google搜索错误会将我带到此页面,因此我将其发布在此处供所有人查看。

我最近遇到了这条错误消息并检出了所有代码行(没有'擦除'或类似内容;只是读取了矢量)。

最终,我意识到嵌套循环存在问题。

例如,考虑这样的事情:

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

当你完成嵌套循环时,它将递增迭代器 - 然后,父循环将再次递增它(!),最终使迭代器步骤超过end()。即如果有这样的事情,它将是“结束()+ 1”。 因此,父循环在下次检查时抛出此错误。

为了解决这个问题,我最终在子循环之后插入了这一行:

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

很脏,但有效:D

我知道这对某些人来说可能是显而易见的,但我一直在摸不着头脑,哈哈尔

答案 5 :(得分:1)

当调用向量的erase方法时,指向已删除元素或删除元素之后的元素的任何迭代器都将失效。 Erase方法返回指向向量中下一个元素的有效迭代器。您应该使用该迭代器继续循环&amp;不增加无效的迭代器。您还可以使用clear方法删除向量中的所有元素。但是,您需要记住明确地为元素重新分配任何已分配的内存。

答案 6 :(得分:1)

此代码泄漏了向量的所有内容 - 您也必须在循环中delete *deleteIterator。您可以使用Base代替Base*作为vector内容来避免所有这些,然后clear()将为您销毁它们。或者使用boost::ptr_vector,如果你需要原始指针,它会自动销毁。

如果erase()很大,那么在这样的前向迭代中调用vector可能会非常昂贵,因为当前位置上方的每个元素都必须向下移动以确保元素保持连续。由于这个原因和其他原因,请避免手动删除您建议的类型。

答案 7 :(得分:0)

向量迭代器是可递增的,但是如果删除元素,则会修改向量内容,因此迭代器无效。

因此,如果删除对象,则应使用erase()的返回值,它将为您提供下一个有效的迭代器。