本人最近工作中用到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;
}
}