调试断言失败.C ++向量下标超出范围

时间:2015-11-12 09:06:44

标签: c++ vector

以下代码应该删除向量中的重复值 例如,如果向量包含{1,5,3,3},则结果应为{1,5,3}

程序启动,我输入整数n*。 但是,该程序会引发以下错误:

  

Debug assertion failed.Program:... \ include \ vector line:932   表达式:向量下标超出范围。

当我按重试时,visual c ++会显示一个新窗口:

  

" try.exe触发了一个断点"。

然后,在我点击“继续”后,会出现另一个错误:

  

调试断言失败!程序:... \ include \ vector line:933   表达式:"标准c ++库超出范围" &安培;&安培; 0

我的代码如下:

#include <iostream>
#include <vector>
using namespace std;
void removeDup (vector<int>& v);

int main()
{
    vector<int> v;
    int i,n;
    cin>>n;
    for(i=0;i<n;i++){
        v[i]=rand()%10;
    }
    removeDup(v);
    for(i=0;i<n;i++)
    {
        cout<<v[i];    
    }
    system("pause");
}

void removeDup(vector<int>& v)
{
    int i,j,size;
    size=v.size();
    for(i=0;i<size;i++)
    {
        for(j=0;j<size;j++)
        {
            if(v[i]==v[j])
            v.erase(v.begin()+j);
        }
    }
}

2 个答案:

答案 0 :(得分:5)

断言失败实际上是在告诉你到底发生了什么。你的向量是零大小的,并且你试图索引一个空的向量(这自然会访问超出范围的东西)。

operator[]不会为像vector这样的标准序列动态创建元素,例如某些语言中的关联数组或std::map的情况。您传递给operator[]的索引必须在[0, vector.size())范围内,否则它将在调试中触发此超出范围的断言失败(对于已检查的实现)或在发布版本中触发潜在的段错误/访问冲突(基本上未定义的行为)。这是出于性能原因而完成的,因为否则需要在operator[]中进行分支,这通常会破坏vector所具有的与数组相当的索引性能(尽管有at方法会抛出它具有分支开销。)

在这里,您需要使用填充构造函数预先调整向量的大小,例如:

int i,n;
cin>>n;
vector<int> v(n);
...

或者在使用operator[]方法resize访问它之前调整其大小:

vector<int> v;
int i,n;
cin>>n;
v.resize(n);

或使用push_backs

vector<int> v;
int i,n;
cin>>n;
// can use reserve here for a performance boost if desired
// since we know the memory capacity needed in advance.
for(i=0;i<n;i++){
    v.push_back(rand()%10);
}

您的removeDup功能还有另外一个问题。那个问题在于你循环遍历向量,好像它的大小没有改变,但是调用一个擦除方法,它会在每次迭代时减小它的大小。这也会调用超出范围的访问权限 - 也许你可以找出解决方案作为练习的一部分(我假设这是一个练习,因为std::unique会做的伎俩)。这里要注意的第一件事可能是operator[]没有为你动态创建元素。

答案 1 :(得分:0)

我给你另一种方法来解决这个问题。(你可以使用它)。 您可以在此处使用#include<set>删除重复值,如下所示:

set<int>s;
    s.insert(10);
    int i,n;
    cin>>n;
    for(i=0;i<n;i++){
        s.insert(rand()%10);
    }
    set<int>::iterator ii;
    for(ii=s.begin();ii!=s.end();ii++)
    cout<<*ii;