概述
本人最近工作中用到std::list,在删除元素时用到以下
for( iterator= List.begin(); iterator!= List.end(); iterator++)
{
if( iterator->nIndex == nIndex)
{
List.erase( iterator);
}
}
结果可想而知,程序异常。在查找网上资料后知道erase方法使用不对,到了现在还犯这种错误,汗颜!吸取教训~
下面将所找的资料贴出来,写的很明白,就不再敷述。
===========================================================================================
【http://www.jb51.net/article/37437.htm】
基于C++ list中erase与remove函数的使用详解
erase的作用是,使作为参数的迭代器失效,并返回指向该迭代器下一参数的迭代器。
如下:
list ParticleSystem;
list::iterator pointer;
if(pointer->dead == true)
{
pointer = ParticleSystem.erase(pointer);
}
有一段关于错误使用erase的程序
using namespace std;
int main()
{
std::listtest_list;
std::list::iterator test_list_it;
test_list.push_back(1);
test_list_it = test_list.begin();
for(;test_list_it != test_list.end();test_list_it++)
{
test_list.erase(test_list_it);
}
}
问题: 该程序不能跳出循环
原因: test_list.erase(test_list_it);每次做erase时都有可能使迭代器失效,test_list_it++就发生错误了。可以参见effective stl一书。所有容器做erase操作时都有可能使迭代器失效。
改为:
for(;test_list_it != test_list.end();)
{
test_list.erase(test_list_it++);
}
or
for(;test_list_it != test_list.end();)
{
std::list::iterator iter_e=test_list_it++;
test_list.erase(iter_e);
}
注意:
for(;test_list_it != test_list.end();test_list_it++;) {
std::list::iterator iter_e=test_list_it;
test_list.erase(iter_e);
}
这样仍然是错误的,原因是:iter_e=test_list_it 是指针值的复制,它俩其实指向同一个位置,所以iter_e失效那么test_list_it也会失效,所以test_list_it++就会有问题
如果是
for(;test_list_it != test_list.end();)
{
std::list::iterator iter_e=test_list_it++;
test_list.erase(iter_e);
}
则没有问题。
remove函数也存在erase函数同样的问题,但remove函数返回值是空,erase返回指向下一个元素的迭代器
===========================================================================================
【http://www.cppblog.com/Herbert/archive/2009/01/08/70479.html】
STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector 、deque);另一类是以不连续的节点形式存储的容器(如:list、set、map)。在使用erase方法来删除元素时,需要注意一些问题。
在使用 list、set 或 map遍历删除某些元素时可以这样使用:
或
下面是两个错误的使用方法:
或
正确使用方法1:通过erase方法的返回值来获取下一个元素的位置
正确使用方法2:在调用erase方法之前先使用 “++”来获取下一个元素的位置
错误使用方法1:在调用erase方法之后使用“++”来获取下一个元素的位置,由于在调用erase方法以后,该元素的位置已经被删除,如果在根据这个旧的位置来获取下一个位置,则会出现异常。
错误使用方法2:同上。
这里“++”运算符与我们平常的理解刚好相反,erase( itList++) 是先获取下一个元素的位置在删除; erase( ++itList) 是删除以后再获取下一个元素的位置。
在使用 vector、deque遍历删除元素时,也可以通过erase的返回值来获取下一个元素的位置:
注意:vector、deque 不能像上面的“正确使用方法2”的办法来遍历删除。
===========================================================================================
【http://www.jb51.net/article/41617.htm】
在使用 list、set 或 map遍历删除某些元素时可以这样使用:
正确使用方法1
std::list< int> List;
std::list< int>::iterator itList;
for( itList = List.begin(); itList != List.end(); )
{
if( WillDelete( *itList) )
{
itList = List.erase( itList);
}
else
itList++;
}
正确使用方法2
std::list< int> List;
std::list< int>::iterator itList;
for( itList = List.begin(); itList != List.end(); )
{
if( WillDelete( *itList) )
{
List.erase(itList++);
}
else
itList++;
}
正确使用方法3
std::list< int> List;
std::list< int>::iterator it, next;
for( it = List.begin(), next = it, next ++; it != List.end(); it = next, ++next)
{
if( WillDelete( *it) )
{
List.erase(it);
}
}
注:方法三更为巧妙,但需注意方法三是用前需要判断容器是否为空,否则迭代器会出问题。
我测试得出,set.erase 不返回迭代器,list返回。
vector 删除操作
std::vector <PACK_PRINT>::iterator It ;
for(It=printItems.begin();It!=printItems.end();)
{
//我是说这里怎么判断printItems printItems 里PACK_PRINT.bh =0
if( It.bh ==0) //是这样吗?
{//删除
It=printItems.erase(It);
}
else
{//不删除
++It;
}
}
std::vector <PACK_PRINT> printItems;
int i = 0;
while(i < printItems.size())
{
if(printItems[i].bh == 0) //这里比如我想把 printItems 时PACK_PRINT.bh =0 的删除如何写哟。另外这样删除有错吗?
{//删除
printItems.erase(printItems.begin() + i);
}
else
{//不删除
++i;
}
}
最后
以上就是繁荣小馒头为你收集整理的stl容器之erase用法的全部内容,希望文章能够帮你解决stl容器之erase用法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复