1、vector中删除满足某些条件的元素和迭代器失效问题
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> mVector;
mVector.push_back(1); //插入元素push_back
mVector.push_back(2);
mVector.push_back(0);
mVector.push_back(3);
mVector.push_back(4);
mVector.push_back(0);
mVector.push_back(0);
mVector.push_back(6);
mVector.push_back(0);
mVector.push_back(0);
std::vector<int>::iterator iter = mVector.begin();
for (; iter != mVector.end(); ) //删除操作
{
if (0 != *iter)
{
++iter;
}
else
{
iter = mVector.erase(iter); //方式一(正确)
//mVector.erase(iter++); //方式二(错误)
//mVector.erase(it); it++; //方式三(错误)
}
for (iter = mVector.begin();; iter != mVector.end(); ++iter)//vector遍历操作
{
std::cout << " " << *iter << " ";
}
return 0;
}
【错误分析】
/*方式三:错误
vv.erase(it); //对vector进行增加删除等操作后之前it可能无效
it++; //删除后it此时已经无效,it成为野指针,不能执行it++操作
/*方式二:错误
该种情况,vector、deque不能用,但是list、map、set可以!
2、list中删除满足某些条件的元素
#include <iostream>
#include <list>
using namespace std;
int main()
{
std::list<int> mList;
mList.push_back(1); //插入操作push_back
mList.push_back(2);
mList.push_back(0);
mList.push_back(3);
mList.push_back(4);
mList.push_back(0);
mList.push_back(0);
mList.push_back(6);
mList.push_back(0);
mList.push_back(0);
std::list<int>::iterator iter = mList.begin();
for (; iter != mList.end(); ) //删除操作
{
if (0 != *iter)
{
++iter;
}
else
{
iter = mList.erase(iter); //方式一(正确)
//mList.erase(iter++); //方式二(正确)
//mList.erase(iter); iter++; //方式三(错误)
}
}
iter = mList.begin();
for (; iter != mList.end(); ++iter) //遍历操作
{
std::cout << " " << *iter << " ";
}
return 0;
}
3、map中删除满足某些条件的元素
注意:对map和set等自动排序的容器不应使用remove一类算法
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main(int argc, char* argv[])
{
map<int, string> mapData;
//插入元素方式(四种)
mapData.insert(pair<int,string>(0,"aaa"));
mapData[1] = "bbb";
mapData.insert(make_pair<int,string>(2,"ccc"));
mapData.insert(map<int,string>::value_type(3,"ddd"));
for (map<int, string>::iterator it=mapData.begin(); it!=mapData.end(); /*it++*/) //删除操作
{
if ((*it).first == 2)
{
it = mapData.erase(it); //方式一(正确)
//mapData.erase(it++); //方式二(正确)
//mVector.erase(it); it++; //方式三(错误)
}
else
{
it++;
}
}
for (map<int, string>::iterator it=mapData.begin(); it!=mapData.end(); it++) //map遍历输出
{
cout<<(*it).first<<" "<<(*it).second<<endl; //取值操作方式 (*it).first和(*it).second
}
return 0;
}
3、set中删除满足某些条件的元素
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int> s;
s.insert(5); //第一次插入5,可以插入
s.insert(1);
s.insert(0);
s.insert(3);
s.insert(5); //第二次插入5,重复元素,不会插入
s.erase(-1);
set<int>::iterator it = s.begin();
for(;it != s.end();) //删除操作
{
if(*it < 2)
{
//it = s.erase(it); //方式一(正确)
//s.erase(it++); //方式二(正确)
//s.erase(it); it++; //方式三(错误)
}
else
it++;
}
for(it = s.begin(); it != s.end(); it++) //遍历操作
cout << *it << " ";
return 0;
}
综上所述,
对于删除操作:
方式一都正确;
方式三都错误;
方式二vector/deque等顺序容器错误、list/map/set等关联容器正确。>
【重点:remove和erase讲解】
1、 erase一般作为一个container的成员函数,是真正删除的元素,是物理上的删除。
2、作为算法项目组的remove类函数,是逻辑上的删除,将被删除的元素移动到容器末尾,然后返回新的末尾,此时容器的size不变更。
3、项目组容器若有成员函数remove,那么代表的是真正物理意义上的删除元素。
4、若是该容器是vector、string或者deque,应用erase-remove idiom或者erase-remove_if idiom。
5、若是该容器是list,应用list::remove或者list:remove_if成员函数。
6、 若是该容器是一个联合 container,应用asso_con::erase成员函数或者remove_copy_if连络swap等体式格式。
7、有一些斗劲特别的容器具现,比如vector等,暂不推敲。【remove和erase对比】 一般情况下,remove是STL的函数,#include < algorithm >,而erase是容器的成员函数,#include <容器> 。 使用remove不能真正的删除元素!
如果你真的要删除东西的话,可以用下面两种形式:erase-remove、erase。
vector<int> v;
v.erase(remove(v.begin(), v.end(), 99), v.end());//删除容器v中的所有的值为99的元素
//[总结]
//使用的固定形式:
//v.erase(remove(v.begin(), v.end(), VALUE), v.end());
//这句的意思是,取得VALUE的位置(位于结尾),然后删除VALUE到原vector结尾的所有元素
// remove all elements from Numbers that match 10
vector<int>::iterator ret = remove(Numbers.begin(), Numbers.end(), 10) ;
【解释】原vector { 10 20 10 15 12 7 9 },删除10,会将10后面的元素移动到前面
(注意以下逐个元素对齐,模拟元素在内存中的位置,这样就容易看出变化规律)
原vector
10 20 10 15 12 7 9
遇到第一个10,数组变成
20 10 15 12 7 9
遇到第二个10移动到7 9之后又遇到第三个10于是剩下内存中未移动的7 9
20 15 12 7 9 7 9
遇到第三个10
20 15 12 7 9 7 9
但是,有特例— — list容器**
对于list,因为list有成员函数remove,因此调用list的remove成员函数可以“真的”删除,且比应用erase-remove惯用法更高效!
list<int> li; // 建立一个list
// 放一些值进去
li.remove(99); // 除去所有等于99的元素
// 真的删除值为99的元素
// 所以list的大小可能改变了