今天一個很早的程序,運行vector erase以後,Debug報“vector iterator not incrementable”。收集記錄一下!
轉自:http://blog.csdn.net/tujiaw/article/details/7770498
- #include <iostream>
- #include <vector>
- #include <list>
- #include <iterator>
- using namespace std;
- void Remove1(vector<int> &vec, int num)
- {
- vector<int>::iterator iter;
- for (iter=vec.begin(); iter!=vec.end(); ++iter)
- {
- if (*iter == num)
- {
- vec.erase(iter);
- }
- }
- }
- void Remove2(list<int> &lst, int num)
- {
- list<int>::iterator iter;
- for (iter=lst.begin(); iter!=lst.end(); ++iter)
- {
- if (*iter == num)
- {
- lst.erase(iter);
- }
- }
- }
- int main(void)
- {
- int arr[] = {1, 3, 5, 5, 7, 9};
- int num = sizeof(arr) / sizeof(arr[0]);
- vector<int> vec(arr, arr+num);
- list<int> lst(arr, arr+num);
- Remove1(vec, 5);
- copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
- //Remove2(lst, 5);
- //copy(lst.begin(), lst.end(), ostream_iterator<int>(cout, " "));
- return 0;
- }
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
using namespace std;
void Remove1(vector<int> &vec, int num)
{
vector<int>::iterator iter;
for (iter=vec.begin(); iter!=vec.end(); ++iter)
{
if (*iter == num)
{
vec.erase(iter);
}
}
}
void Remove2(list<int> &lst, int num)
{
list<int>::iterator iter;
for (iter=lst.begin(); iter!=lst.end(); ++iter)
{
if (*iter == num)
{
lst.erase(iter);
}
}
}
int main(void)
{
int arr[] = {1, 3, 5, 5, 7, 9};
int num = sizeof(arr) / sizeof(arr[0]);
vector<int> vec(arr, arr+num);
list<int> lst(arr, arr+num);
Remove1(vec, 5);
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
//Remove2(lst, 5);
//copy(lst.begin(), lst.end(), ostream_iterator<int>(cout, " "));
return 0;
}
請看上面的Remove1、Remove2這兩個函數是刪除容器中所有爲num的元素, 乍一看好像沒什麼問題, 其實是錯的。
它們編譯都沒什麼問題,但是運行有問題:
先註釋Remove2這兩行, 編譯運行, 得到結果是:1 3 5 7 9
顯然結果是錯誤的,因爲還有個5沒刪掉。造成這樣結果的原因是vec.erase之後iter會自加,執行下次for循環時++iter,這樣就跳過了與所刪除元素相鄰的元素了。
再來看下Remove2, 註釋掉Remove1, 刪除Remove2的註釋。
運行出錯,vs2005 Expression:list iterator not incrementable,說明list迭代器++iter有問題。
list是一個雙向鏈表,在erase(iter)之後iter失效了,printf("0x%x", iter);得到結果爲0,只有erase的返回值才能指向下一個元素。
Remove1的正確用法是:vec.erase(remove(vec.begin(), vec.end(), 5), vec.end());
Remove2的正確用法是:lst.remove(5);
下面是另一種正確寫法:
- void Remove1(std::vector<int> &vec, int num)
- {
- std::vector<int>::iterator iter = vec.begin();
- while (iter != vec.end())
- {
- if (*iter == num)
- {
- iter = vec.erase(iter);
- }
- else
- {
- ++iter;
- }
- }
- }
- // 刪除某一類元素, 比如:偶數
- void Remove3(std::set<int>& sets)
- {
- std::set<int>::iterator iter = sets.begin();
- while (iter != sets.end())
- {
- if (0 == (*iter)%2)
- {
- // 注意這裏不能寫成++iter,後面說明原因
- sets.erase(iter++);
- }
- else
- {
- ++iter;
- }
- }
- }
- void Remove4(std::map<int, int>& maps)
- {
- std::map<int, int>::iterator iter = maps.begin();
- while (iter != maps.end())
- {
- if (0 == (iter->first)%2)
- {
- maps.erase(iter++);
- }
- else
- {
- ++iter;
- }
- }
- }
void Remove1(std::vector<int> &vec, int num)
{
std::vector<int>::iterator iter = vec.begin();
while (iter != vec.end())
{
if (*iter == num)
{
iter = vec.erase(iter);
}
else
{
++iter;
}
}
}
// 刪除某一類元素, 比如:偶數
void Remove3(std::set<int>& sets)
{
std::set<int>::iterator iter = sets.begin();
while (iter != sets.end())
{
if (0 == (*iter)%2)
{
// 注意這裏不能寫成++iter,後面說明原因
sets.erase(iter++);
}
else
{
++iter;
}
}
}
void Remove4(std::map<int, int>& maps)
{
std::map<int, int>::iterator iter = maps.begin();
while (iter != maps.end())
{
if (0 == (iter->first)%2)
{
maps.erase(iter++);
}
else
{
++iter;
}
}
}
set和map是由紅黑樹來實現的,當erase的時候迭代器就失效了,也就是說我們要在迭代器失效之前
保留一個副本,根據這個副本我們才能繼續遍歷下一個元素。i++和++i很明顯前者符合我們的要求所以
在erase裏面是iter++