最近刚刚学习了c++的容器,简直是打开了新的世界,觉得自己以前编写的c语言程序真的是效率低下的恐怖,但是容器里面这个类似指针的迭代器也是藏着很多有意思的事情。
最近做了个程序,大致要求是通过遍历,把容器中符合一定要求的值删去。
于是我兴致冲冲的写了如下一段
for(vector<int>::iterator it=v1.begin();it!=v1.end();it++)
{
for(vector<int>::iterator itv=vadj.begin();itv!=vadj.end();itv++)
{
if(CB(*it+*itv))//没超界
{
if(!Lattice(*it+*itv,V_RICT))//没这个点
{
it=V_CICT.erase(it);
break;
}
}
}
}
看似没有问题,连Vector的erase方法会导致迭代器消失需要重新把它的返回值赋给迭代器都考虑到了,但是这个程序是有bug的,如果倒数第二个元素整好需要被删除,那么,最后一个元素无法被访问。原因在于erase方法使迭代器后移了一个位置,而for循环又后移了一次,会导致有的元素无法被访问,甚至迭代器运行时报错。
这种情况我是改用while循环做第一层循环,用一个bool量做标志进行筛选。
bool del=true;//由于erase会自己向下挪动一个位置的指针,
vector<int>::iterator it=V_CICT.begin();
while(it!=V_CICT.end())
{
if(!del)
{
it++;
}
for(vector<int>::iterator itv=vadj.begin();itv!=vadj.end();itv++)
{
del=false;
if(CB(*it+*itv))//没超界
{
if(!Lattice(*it+*itv,V_RICT))//没这个点
{
it=V_CICT.erase(it);
del=true;
break;
}
}
}
}
问题解决,所以使用容器的迭代器遍历时一定注意迭代器的具体轨迹,像Vector如果只是单纯遍历访问可以使用【】的访问方式更加的直观。