【问题标题】:Runtime Error when erasing elements from std::vector从 std::vector 擦除元素时出现运行时错误
【发布时间】:2013-06-14 10:23:36
【问题描述】:

我有一个向量index,其中包含我要删除的元素的索引 来自矢量words

vector<int> Index;
vector<int> words;

我尝试使用此方法,但我的程序在运行时崩溃,为什么? 发生了什么?

for(int t1 = 0; t1 < index.size(); t1++)
{
        words.erase(words.begin()+ index[t1])
}

谢谢。

【问题讨论】:

  • 问题:您的词向量在每次擦除(大小、迭代器等)后更新,但不是您的索引向量,因此每次后续迭代都会删除不需要的元素,并且在一个实例中索引向量返回的索引是Word 向量中不存在。解决方案:您可以在下面发布的答案中找到它。请接受您所需要的满意答案。

标签: c++ vector erase


【解决方案1】:

如果不了解您如何声明和初始化wordsindex,就很难准确地判断程序崩溃的原因。

但是,最有可能发生的情况是,在从words 中删除一个元素之后,并且在所有后续元素都向左移动了一个位置之后,index 中的索引可能会索引超出的位置向量的新端。

i 大于向量的大小时,评估words.begin() + i 将导致未定义的行为(在您的情况下表现为崩溃)。

如果您的索引向量按升序排序,只需还原您的循环:

for(int t1 = index.size() - 1; t1 >= 0; --t1)
{
    words.erase(words.begin() + index[t1]);
}

或者,您可以使用原始循环并按递减顺序对索引进行排序。

【讨论】:

  • vector words 是一个整数向量 v​​ector index 包含我必须从 word 中删除的整数的索引第 1 步:我对向量进行排序 Index sort(index.begin() ,index.end()); Step2:我遍历单词以删除元素
【解决方案2】:

这里的问题是,当你擦除其中的一些元素时,你正在更新向量的大小。

试试这个:

for(int t1 = index.size()-1; t1 >= 0; --t1)
{
    words.erase(words.begin()+index[t1])
}

【讨论】:

  • vector words 是一个整数向量 v​​ector index 包含我必须从 word 中删除的整数的索引第 1 步:我对向量进行排序 Index sort(index.begin() ,index.end()); Step2:我遍历单词以删除元素
  • @HaniGoc: 嗯,所以问题有点复杂,当你删除向量的一个元素时,它会重新排列向量的内容。
  • words.erase(words[index[t1]]) 错误:没有匹配函数调用 std::vector::erase(int&)
  • 哦,我明白了,你的意思是我应该减少索引向量Index?
  • @Kevin 也许您应该在回答中详细说明问题。对于曾经(不止一次 ;-) )绊倒的人来说很清楚:如果您从向量中删除元素,则索引会更改,但只有那些引用了被删除元素之后的元素的索引才会变得无效。所以通过反向迭代进行擦除是省钱的,而正向迭代需要额外的努力。
【解决方案3】:

尝试反向执行操作。删除后续索引后,后续索引将失效。

我假设您的索引是有序的。如果不是,则对它们进行排序,然后确保首先删除最大的索引。

【讨论】:

    【解决方案4】:
    vector<int>a = {0,0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0};
    vector<int>index;
    int t = 0;
    while(t < a.size() && a[t] != 1)
    {
        index.push_back(t);
        t = t + 1;
    }
    
    t = a.size()-1;
    while( t > 0 && a[t] != 1)
    {
        index.push_back(t);
        t = t - 1;
    }
    sort(index.begin(),index.end());
    index.erase(std::unique(index.begin(), index.end()), index.end());
    cout << "Before: ";
    for(int i = 0; i <a.size();i++)
    {
       cout << a[i] <<"   ";
    }
    
    
    cout << endl;
    int counter = 0;
    for(int i = 0; i < index.size();i++)
    {
        a.erase(a.begin() + (index[i]-counter));
        counter = counter + 1;
    }
    
    cout <<"After: ";
    for(int i = 0; i < a.size();i++)
    {
       cout << a[i] <<"   ";
    }
    

    【讨论】:

    • 正如你在这里看到的,我不得不使用计数器来保持索引向量的更新。我不知道我希望找到更简单的解决方案。谢谢大家的帮助。
    • 我觉得很难理解,这段代码到底做了什么。坦率地说,我会坚持 Kevins 的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    相关资源
    最近更新 更多