erase的函数原型有两种形式:
iterator erase(iterator position); iterator erase(iterator first, iterator last);
例如有一个类A,
class A { public: int id; A(void); ~A(void); };
定义vector<A*> vec
for (int i=0; i<10; i++) { A *p = new A(); p->id = i; vec.push_back(p); }
下面要删除vec中id为5的元素:
for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); iter++) { if(5 == (*iter)->id) { delete *iter; veci.erase(iter); } }
初看这段代码没什么问题,实际上其中存在很大的问题;当调用erase方法后,iter就变成了一个野指针,继续循环iter++就出错了。
那我们继续修改代码:
for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); iter++) { if(5 == (*iter)->id) { delete *iter; iter = veci.erase(iter); } }
erase返回值是这样的:An iterator that designates the first element remaining beyond any elements removed, or a pointer to the end of the vector if no such element exists
仔细阅读上面的代码实际上也有问题,首先代码不能删除连续两个为5的元素,因为删除第一个之后,iter指向第二个,自增后,就指向了第二个后面了;其次如果元素5位于vector最后,删除后iter自增也会出错。
那么正确的写法可以如下:
for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); ) { if(5 == (*iter)->id) { delete *iter; iter = veci.erase(iter); } else { iter++; } }
这样就可以解决连续两个相同元素的问题,同时将要删除的元素位于最后的话,也不会有问题,因为删除后,erase返回vector.end()。
其实还可以采用另一种方法,在STL的算法中有一个函数remove,这个函数可以将迭代器范围内的等于某个值的元素“删除“(这里的删除是不改变容器的 大小,只是将一些不满足条件的元素前移,这样的话保留的元素都移到了容器的前面,而remove正好就指向这些保留元素后的第一个元素,而后面的就是要删 除的。)然后执行erase操作就可以了
void remove_v2(vector<int>& v,int val){
v.erase( remove(v.begin(),v.end(),val), v.end() );
}
时间: 2024-10-11 22:56:16