【问题标题】:invalid iterator after STL vector eraseSTL 向量擦除后的无效迭代器
【发布时间】:2014-10-23 13:09:51
【问题描述】:

即使我查看了该页面:http://www.cplusplus.com/reference/vector/vector/erase/, 我仍然不明白为什么在执行以下代码的最后一行时在 VS2010 上出现运行时错误('vector iterator not incrementable'):

vector<int> vec;
for(int i = 0 ; i < 10 ; i++)
    vec.push_back(i);
auto itb = vec.begin()+1;  // 2nd item of the vector
auto it  = itb + 2;        // 4th item of the vector
it = vec.erase(itb, it);   // remove the 2nd & 3rd
++it; // Error happens when trying to execute this line

我认为擦除会在最后一个删除的项目之后返回一个迭代器。 所以,这里它将指向值为 3 的项目。 在这里,由于向量足够长,因此擦除不会返回 vec.end()。 从那里,我应该能够使用有效的迭代器进行迭代。 但不是! 为什么?

该代码有效:

vector<int> vec;
for(int i = 0 ; i < 10 ; i++)
    vec.push_back(i);
auto itb = vec.begin()+1;
auto it = itb + 2;
vec.erase(itb, it);
it = vec.begin()+1; // re-generate an iterator from the begin() one.
++it;

编辑: 如果我在一个空的 main.cpp 文件中稍微修改“来自莫斯科的 Vlad”(见下文)的代码,那么我仍然遇到问题。所以,我想我有一个编译器问题。

代码如下:

#include <iostream>
#include <vector>
int main() 
{
    std::vector<int> v;
    for ( int i = 0; i < 10; i++ ) v.push_back( i );

    for ( auto it = v.begin(); it != v.end() ; ++it ) std::cout << *it << ' ';
    std::cout << std::endl;

    auto itb = v.begin() + 1;
    auto it = itb + 2;

    it = v.erase( itb, it );

    ++it;  // Crash here

    for ( auto it = v.begin(); it != v.end() ; ++it ) std::cout << *it << ' ';
    std::cout << std::endl;

    while ( it != v.end() ) std::cout << *it++ << ' ';
std::cout << std::endl;

    return 0;
}

让我描述一下我的配置: 我在并行桌面 (Mac) 下运行 Win7 Ultimate 64bit,安装了 VC++6、VCS2003、VS2005、VS2008、VS2010(无 SP,.Net framework 4.5)。

【问题讨论】:

  • 请记住,您的循环可能只是对 std::iota 的调用。
  • 该代码没有问题。你确定它是你正在运行的那个吗?
  • 如果程序在上面使用 sn-p 的那一行崩溃,您可能在其他地方有未定义的行为会破坏内存。
  • 你检查it != vec.end()以防万一吗?擦除后尝试打印it
  • 你在使用奇怪的编译器吗?否则你会在其他地方破坏迭代器。

标签: c++ vector stl


【解决方案1】:

这个例子证明你的第一个代码sn-p没有错

#include <iostream>
#include <vector>


int main() 
{
    std::vector<int> v;
    for ( int i = 0; i < 10; i++ ) v.push_back( i );

    for ( int x : v ) std::cout << x << ' ';
    std::cout << std::endl;

    auto itb = v.begin() + 1;
    auto it = itb + 2;

    it = v.erase( itb, it );

    ++it;

    for ( int x : v ) std::cout << x << ' ';
    std::cout << std::endl;

    while ( it != v.end() ) std::cout << *it++ << ' ';
    std::cout << std::endl;

    return 0;
}

输出是

0 1 2 3 4 5 6 7 8 9 
0 3 4 5 6 7 8 9 
4 5 6 7 8 9 

如果要删除语句

    ++it;

那么输出将是

0 1 2 3 4 5 6 7 8 9 
0 3 4 5 6 7 8 9 
3 4 5 6 7 8 9 

编辑:这是在 MS VC++ 2010 中运行的相同程序

#include    "stdafx.h"
#include    <iostream>
#include    <vector>

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> v;
    for ( int i = 0; i < 10; i++ ) v.push_back( i );

    for each ( int x in v ) std::cout << x << ' ';
    std::cout << std::endl;

    auto itb = v.begin() + 1;
    auto it = itb + 2;

    it = v.erase( itb, it );

    ++it;

    for each ( int x in v ) std::cout << x << ' ';
    std::cout << std::endl;

    while ( it != v.end() ) std::cout << *it++ << ' ';
    std::cout << std::endl;
}

我希望这些例子能帮助你找到真正的错误。

【讨论】:

  • 我想我遇到了编译器问题,因为我尝试了您的上层代码(稍作修改以不使用“自动循环”进行打印),但我仍然遇到同样的问题。
  • @OhMyCode 我的帖子包含一个在 MS VS 2010 中运行的示例。所以可能是您修改的原因。另一个原因可能是编译器使用了错误的头文件。
  • 是的,但是我懒得重新创建一个项目。所以,我只是#if 0/#endif 我的代码并把你的第一个(因为我总是禁用 stdafx.h 的东西,因为我的代码需要是可移植的)。否则,“向量”。它崩溃的文件位于“C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include”中。
猜你喜欢
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
相关资源
最近更新 更多