C++ STL中erase函数的用法 求助~~

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ STL中erase函数的用法 求助~~相关的知识,希望对你有一定的参考价值。

请大家来看一下这个erase函数到底怎么用 这个程序编译倒是能通过 可运行时会显示错误 “嘭”一声弹出个对话框Debug Assertion Failed!我觉得肯定是erase函数用法不对 可是找不到错误在哪儿 请大家指导一下了~~~

对了程序功能是删除vector对象中的偶数和list对象中的奇数

#include<iostream>
#include<vector>
#include<list>
using namespace std;
int main()

int ia[10]=2,3,4,5,6,7,8,9,10,11;
vector<int> ivec(ia,ia+10); //定义一个vector对象ivec
vector<int>::iterator iter=ivec.begin();
list<int> lvec(ia,ia+10); //定义一个list对象lvec
list<int>::iterator lter=lvec.begin();
while(iter!=ivec.end() && lter!=lvec.end())

if(*iter%2==0)
ivec.erase(iter);
if(*lter%2!=0)
lvec.erase(lter);
++iter;
++lter;

for(iter=ivec.begin(); iter!=ivec.end(); ++iter)
cout<<*iter<<" ";
cout<<endl;
for(lter=lvec.begin(); lter!=lvec.end(); ++lter)
cout<<*lter<<" ";
cout<<endl;
system("PAUSE");
return 0;

对于vector一般不要用erase(),因为很多情况下他要和<algorithm>中的remove()一块用!erase()的使用会使迭代器失效如果删除的不是最后面的元素的话。你的程序中if(*iter%2==0) ivec.erase(iter); 可以换成:(记着加头文件<algorithm>)

if (*iter%2 == 0)
ivec.erase(remove(ivec.begin(), ivec.end(), *iter), ivec.end())
但如果你用if (*iter%2 != 0)
ivec.erase(remove(ivec.begin(), ivec.end(), *iter), ivec.end())
输出结果则包含11,结果错误!
不知道你为什么数组,向量,链表都用,为了和你一致,我也只能改成这样:
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <iterator>
using namespace std;

int main ()

vector<int> ivec;
list<int> ilis;

int vec[] = 2, 3, 4, 5, 6, 7, 8, 9, 10, 11;

remove_copy_if (vec, vec+10, back_inserter(ivec),
bind2nd(modulus<int>(), 2));

remove_copy_if (vec, vec+10, back_inserter(ilis),
not1(bind2nd(modulus<int>(), 2)));

for (vector<int>::const_iterator iter = ivec.begin();
iter != ivec.end(); ++iter)
cout << *iter << '\t';
cout << endl;

for (list<int>::const_iterator liter = ilis.begin();
liter != ilis.end(); ++liter)
cout << *liter << '\t';
cout << endl;

最好的做法是:
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <iterator>

using namespace std;

int main ()

vector<int> ivec, odd_vec, even_vec;

for (int i = 2; i != 12; ++i)
ivec.push_back(i);

remove_copy_if (ivec.begin(), ivec.end(),
back_inserter(even_vec), bind2nd(modulus<int>(), 2));

remove_copy_if (ivec.begin(), ivec.end(),
back_inserter(odd_vec), not1(bind2nd(modulus<int>(), 2)));

copy (even_vec.begin(), even_vec.end(),
ostream_iterator<int>(cout, "\t"));
cout << endl;

copy (odd_vec.begin(), odd_vec.end(),
ostream_iterator<int>(cout, "\t"));
cout << endl;
参考技术A ivec.erase(iter);
这句执行后,iter变成了野指针,无法再执行 ++ 操作了
试着这么写
if(*iter%2==0)
ivec.erase(iter++);
continue;


lter 也是一样的。
参考技术B ivec.erase(iter); 这个不是erase的问题,而是你用了这个而ivec里面的数据了,所以此时的iter不会起作用了。你可以单步调试看下的 参考技术C 楼上的都先去好好看看书吧

#include<iostream>
#include<vector>
#include<list>
using namespace std;
int main()

int ia[10]=2,3,4,5,6,7,8,9,10,11;
vector<int> ivec(ia,ia+10); //定义一个vector对象ivec
vector<int>::iterator iter=ivec.begin();
list<int> lvec(ia,ia+10); //定义一个list对象lvec
list<int>::iterator lter=lvec.begin();
while(iter!=ivec.end() && lter!=lvec.end())

//////////////////////////////
//注意,erase之后迭代器返回指向删除元素后一位置的引用
//只有当没有操作的时候才需要后移
//////////////////////////////
if(*iter% 2== 0)
ivec.erase(iter);
else
iter++;
if(*lter %2 != 0)
lvec.erase(lter);
else
lter++;

for(iter=ivec.begin(); iter!=ivec.end(); ++iter)
cout<<*iter<<" ";
cout<<endl;
for(lter=lvec.begin(); lter!=lvec.end(); ++lter)
cout<<*lter<<" ";
cout<<endl;
system("PAUSE");
return 0;
参考技术D while(iter!=ivec.end() && lter!=lvec.end())

if(*iter%2==0)
ivec.erase(iter);
if(*lter%2!=0)
lvec.erase(lter);
++iter;
++lter;


楼主注意:
erase()使所有删除点之后的迭代器失效,但对于删除点上和删除点之前的迭代器没有影响。
所以你++lter有问题。
如果你用反向遍历就会很好的说了:
for (lter = ivec.end(); lter != ivec.begin(); lter--)
...

STL函数——remove函数

1. remove函数

remove是STL中的函数,和erase是有区别的:

(1)erase是容器自带的成员函数,而remove是STL中的函数;

(2)erase是真正的删除,而remove是虚假的删除。(下面会说明)

作用

顾名思义,该函数作用是移除容器中的元素。

参数

参数有三个:
头指针、尾指针和要删除的元素。

int b[] = {1,2,3,4,5,5,6};
vector<int> a(b, b+7);
vector<int>::iterator it1 = remove(a.begin(), a.end(), 5);

返回值

remove返回值为一迭代器,指向删除后的真正结尾。(之后会解释)

2. 错误用法

int b[] = {1,2,3,99,5,99,7,8,9,99};
vector<int> a(b, b+10);
vector<int>::iterator it;
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl;
remove(a.begin(), a.end(), 99);
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
//我们期望的输出:1 2 3 5 7 8 9

我们看实际输出的结果是什么:
在这里插入图片描述
并不是我们想的那样,为什么?

3.remove的执行过程

remove函数并不会“真正地”对特定元素进行删除,它只会移动指定区间中的元素直到所有“不删除的”元素在区间的开头(相对位置不变),并返回此时的newEnd迭代器,newEnd后的元素值保持不变。

示意图:
remove前:
在这里插入图片描述
remove后:
在这里插入图片描述
所以我们说,remove只是虚假的删除,因为容器的size并没有变。

【举例】

int b[] = {1,2,3,99,5,99,7,8,9,99};
vector<int> a(b, b+10);
vector<int>::iterator it;
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl;
vector<int>::iterator newEnd = remove(a.begin(), a.end(), 99);
for(it=a.begin(); it!=newEnd; it++)
    cout<<*it<<" ";
cout<<endl<<a.size();

在这里插入图片描述

4. 如何真正删除

搭配容器自带的erase函数,即可真正删除
【举例】

int b[] = {1,2,3,99,5,99,7,8,9,99};
vector<int> a(b, b+10);
vector<int>::iterator it;
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl;
vector<int>::iterator newEnd = remove(a.begin(), a.end(), 99);
a.erase(newEnd, a.end());
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl<<a.size();

在这里插入图片描述
值得注意的是,list自带有remove成员函数(vector等容器没有),用法和erase+remove相同,且效率更高:
【举例】

list<int> l = {1,2,3,99,5,99,7,8,9,99};
l.remove(99);
for(list<int>::iterator it=l.begin(); it!=l.end(); it++)
    cout<<*it<<" ";
cout<<endl<<l.size();

在这里插入图片描述

以上是关于C++ STL中erase函数的用法 求助~~的主要内容,如果未能解决你的问题,请参考以下文章

C++ STL 中 remove 和 erase 的区别

C++ STL 中 remove 和 erase 的区别

[转] C++ STL中map.erase(it++)用法原理解析

C++中stl模版中的erase()和end()(和我之前提的问题不一样)

C++ STL 中 remove 和 erase 的区别

c++ STL map 中erase()后++会指向那个元素?以及erase后map将会自动做啥操作(也就是会怎么变动)?