erase函数的问题

飞飞1984 2009-02-15 07:16:52
//c++ primer里的一道题,在VC 6.0中可以运行,为什么在vs 2005里报Debug Assertion Failed?
//题目如下:假如有如下ia定义,将ia赋值到一个vector容器和一个list容器中。使用单个迭代器参数版本的erase函数将list容器中的奇数值元素删除,将vector容器中的偶数值元素删除。
//int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89, 90, 100 };
//编写的代码如下:

#include <iostream>
#include <vector>
#include <list>
using namespace std;

int main()
{
int ia[ ] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89, 90, 100 };
size_t n = sizeof(ia) / sizeof(*ia);
vector<int> ivec(ia, ia + n);
list<int> ilist(ia, ia + n);

for (vector<int>::iterator viter=ivec.begin(); viter!=ivec.end(); ++viter)
{
if (*viter % 2 ==0)
{
viter = ivec.erase(viter);
--viter; //这里报错
}
}

for (list<int>::iterator liter=ilist.begin(); liter!=ilist.end(); ++liter)
{
if (*liter % 2 != 0)
{
liter = ilist.erase(liter);
--liter;
}
}

return 0;
}
...全文
183 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
飞飞1984 2009-02-15
  • 打赏
  • 举报
回复
最后总结了一下,以便于别人别再犯此类错误,貌似是这样的(环境:VS2005)
/************************************************************************************
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <list>
using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
int ia[ ] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
size_t n = sizeof(ia) / sizeof(*ia);
vector<int> ivec(ia, ia + n);
list<int> ilist(ia, ia + n);

for (vector<int>::iterator viter=ivec.begin(); viter!=ivec.end(); ++viter)
{
if (*viter % 2 ==0)
{
viter = ivec.erase(viter);
--viter;
}
}
for (list<int>::iterator liter=ilist.begin(); liter!=ilist.end(); ++liter)
{
if (*liter % 2 != 0)
{
liter = ilist.erase(liter); //这里貌似循环第一次就不行,(这里前几个元素是0, 1, 1.0, 2)
//(为了好区分,第二个1写成1.0)
//因为0是偶数,erase函数执行完迭代器指向第一个1,容器中元素变为(1, 1.0, 2)
--liter; //这里又--,迭代器前移,但是这时候1前面已经没有元素了,所以报错了…
}
}

for (vector<int>::iterator iter=ivec.begin(); iter!=ivec.end(); ++iter)
cout << *iter << " ";
cout << endl;
for (list<int>::iterator iter2 = ilist.begin(); iter2!=ilist.end(); ++iter2)
cout << *iter2 << " ";
cout << endl;

return 0;
}
***********************************************************************************/:
lei_zhuyan 2009-02-15
  • 打赏
  • 举报
回复
改正后的代码(只处理了VECTOR):

--------------------------
#include <iostream>
#include <vector>
#include <list>
using namespace std;

int main()
{
int ia[ ] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89, 90,100 };
size_t n = sizeof(ia) / sizeof(*ia);
vector <int> ivec(ia, ia + n);
list <int> ilist(ia, ia + n);

bool flag = true; // flag 表示数组的个数为奇数
if (n %2 == 0)
flag = false;

size_t i = flag? 1: 0;
while (ivec.size()-i >0)
{
ivec.erase(ivec.end()-1 - i);
i++;
}

for (vector<int>::iterator i= ivec.begin(); i!= ivec.end(); i++)
cout << *i << endl;
system("PAUSE");


return 0;
}


飞飞1984 2009-02-15
  • 打赏
  • 举报
回复
谢谢lei_zhuyan ,谢谢各位了,6楼老大的程序应该是没问题了。
貌似是错在了第一次执行erase函数的时候,但VC6.0居然能正常运行,真是奇怪。
lei_zhuyan 2009-02-15
  • 打赏
  • 举报
回复
#include <iostream>
#include <vector>
using namespace std;

int main()
{
int ia[ ] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89, 90, 100 };
vector <int> ivec(ia, ia + 12);

vector<int>::iterator i = ivec.begin();

ivec.push_back(10);
cout << *i << endl; // 迭代器i失效,虽然编译通过,但是运行时就出现了错误;

system("PAUSE");


return 0;
}
lei_zhuyan 2009-02-15
  • 打赏
  • 举报
回复
这样下次循环++iter的时候就相当于跨过了被删的那个元素。


你这样的理解是错的。可以找个简单的代码试试。
飞飞1984 2009-02-15
  • 打赏
  • 举报
回复
增加或者删除vector中的数据是会使迭代器失效,
但是貌似这里应该没问题吧?
viter = ivec.erase(viter); //erase函数返回一个迭代器,指向被删除元素的下一个元素,然后把这个返回的迭代器再赋给iter
--iter;//迭代器再回退,指向被删元素的前一个元素,
这样下次循环++iter的时候就相当于跨过了被删的那个元素。
jakqigle 2009-02-15
  • 打赏
  • 举报
回复
作者code在vs2003上也没有问题。可能编译器有做了改进,请参考编译器文档。

tangshuiling 2009-02-15
  • 打赏
  • 举报
回复

了解earse的返回值是目前楼主需要知道的,参考下列代码

#include <iostream>
#include <vector>
#include <list>
using namespace std;

int main()
{
int ia[ ] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89, 90, 100 };
size_t n = sizeof(ia) / sizeof(*ia);
vector <int> ivec(ia, ia + n);
list <int> ilist(ia, ia + n);

for (vector <int>::iterator viter=ivec.begin(); viter!=ivec.end(); )
{
if (*viter % 2 ==0)
{
viter = ivec.erase(viter);
}
else
++viter;
}

for (list <int>::iterator liter=ilist.begin(); liter!=ilist.end(); )
{
if (*liter % 2 != 0)
{
liter = ilist.erase(liter);
}
else
++liter;
}

return 0;
}
飞飞1984 2009-02-15
  • 打赏
  • 举报
回复
增加或者删除vector中的数据是会使迭代器失效,
但是这里貌似应该没错吧…
viter = ivec.erase(viter); //这里的ivec.erase(viter);返回了一个迭代器,指向被删除元素的下一个元素,然后把这个迭代器再赋给iter.
--iter //再把iter前移,这样下次循环++iter的时候又可以指向下一个元素
lei_zhuyan 2009-02-15
  • 打赏
  • 举报
回复
我绝对相信C++ PRIMER 里面有这样类似的一句话:
增加或者删除vector中的数据会使迭代器失效。

因为我也这样犯过错,给我不小教训 ... ^_^
lei_zhuyan 2009-02-15
  • 打赏
  • 举报
回复
V6能够运行的话,绝对是V6错误了、


如果要对VECTOR增加,删除元素,迭代器就失效。也就是不能再用了。

for (vector <int>::iterator viter=ivec.begin(); viter!=ivec.end(); ++viter)
{
if (*viter % 2 ==0)
{
viter = ivec.erase(viter);
--viter; //这里报错
}
}

在进入循环时,ivec.erase(viter) 删除了一个元素,那么viter就已经失效了、

可以这样改吧(如果数组的个数是奇数的话) :
size_t i = 1;
while (ivec.size() - i >=0)
{
ivec.erase(ivec.end()-1 - i);
i++;
}


如果要删除增加元素的话,通过ivec.end()来处理。ivec.end() 始终是容器的最后一个元素的下一个位置。
cppfaq 2009-02-15
  • 打赏
  • 举报
回复
Mark, seems ok to me
飞飞1984 2009-02-15
  • 打赏
  • 举报
回复
迭代器--了啊
而且vc 6.0为什么正常运行啊…
lei_zhuyan 2009-02-15
  • 打赏
  • 举报
回复
当然得报错了...
当你对迭代器进行删除或者增加元素的时候,迭代器就会失效。

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧