习题9.26原答案出错的解决
解决代码如下:
#include <iostream>
include <vector>
include <list>
using namespace std;
int main()
{
int a[]={0,1,1,2,3,5,8,13,21,55,89};
int cnt=sizeof(a)/sizeof(int);
vector<int> ivec_a(a,a+cnt);
list<int> ilist_a(a,a+cnt);
for(vector<int>::iterator viter=ivec_a.begin();viter!=ivec_a.end();)
{
//代码的关键部分是这里,原答案认为删除指定元素后,迭代器指向下一个元素,
//所以应该减一,以便在原答案的for循环里自动加1,但经过调试发现当删除一个
//元素后,再次调用begin()函数发现容器的开始处已经由原先的0变成了1;
//此时若是把返回来的viter减1为0,则出现未定义,所以报错。
if(0==*viter%2)
viter=ivec_a.erase(viter);
else viter++;
}
for (list<int>::iterator liter=ilist_a.begin();liter!=ilist_a.end();)
{
if (0!=*liter%2)
liter=ilist_a.erase(liter);
else liter++;
}
cout<<"New vector is:"<<endl;
for(vector<int>::iterator viter=ivec_a.begin();viter!=ivec_a.end();viter++)
cout<<*viter<<' ';
cout<<endl;
cout<<"New list is:"<<endl;
for (list<int>::iterator liter=ilist_a.begin();liter!=ilist_a.end();liter++)
cout<<*liter<<' ';
cout<<endl;
return 0;
}
所以现在的解决方法是删除后迭代器是自动指向被删除元素的下一个元素,那么就不必对迭代器进行任何操作,下次循环正好对被删除元素的下一个元素操作,反而在没有删除时,需要手动更新迭代器的指向,指向容器中的下一个元素。
假设我们把头两个数换成8,9,将代码稍作修改,会发现在将第一个8删除之后,再去调用begin函数,那么产生的新迭代器是指向9的,也就是说删除一个元素之后,容器本身就进行了更新,此时删除8之后viter指向了新容器的begin处,所以不能进行减操作。
int a[]={8,9,1,2,3,5,8,13,21,55,89};
int cnt=sizeof(a)/sizeof(int);
vector<int> ivec_a(a,a+cnt);
list<int> ilist_a(a,a+cnt);
for(vector<int>::iterator viter=ivec_a.begin();viter!=ivec_a.end();viter++)
{
if(0==*viter%2)
viter=ivec_a.erase(viter);
viter--;
vector<int>::iterator newviter=ivec_a.begin();
//此时newviter指向9
}
这道题正好在容器的开头处,所以出现报错,但是如果在容器中间的话,删除之后也是不能减的,原因大家应该也清楚了,不过应该不会报错,只是逻辑不对,同一个元素处理了两次。