C++中Vector的erase()操作以及与remove的区别

来源:互联网 发布:创建表时外键的sql语句 编辑:程序博客网 时间:2024/06/06 09:34

部分内容转载地址:http://blog.sina.com.cn/s/blog_6377b8e60100ino6.html

vector <int> v;

v.pushback(0);

v.pushback(1);

v.pushback(1);

v.pushback(0);

想要删除值为1的元素

错误代码

 vector<int>::iterator itr = v.begin();
   while (itr!=v.end())
   {
    if (*v==1)
    {
          v.erase(itr);
     }
    itr++;//这里删除后迭代器会更新出错
   }

 

分析原因::当执行veci.erase(iter)后,迭代器iter指向了哪里?(转自别处)

是时候关注一下erase方法的返回值了:

An iterator pointing to the new location of the element that followed the last element erased by the function call. This is the container end if the operation erased the last element in the sequence.

Member type iterator is a random access iterator type that points to elements.

看到random你就要疯掉了吧,野指针!!!!

也就是说veci.erase(iter)后,iter的状态是不确定的,再进行++,岂有不崩溃的道理!

正确代码

 vector<int>::iterator itr = v.begin();
   while (itr!=v.end())
   {
    if (*v==1)
    {
          itr=v.erase(itr);
     }

else
    itr++;
   }

 

关于迭代器机制,好好研究。参见 http://blog.csdn.net/bruce_wang_janet/article/details/6879289

 

每一次删除之后,后边的元素都会向前移动。

所以当前迭代器实际已经指向下一个元素,若再+1,实际上是指向了下一个元素的下一个元素。

以下为上述程序的详细执行过程

int main(int argc, char* argv[])
{

 vector<int> v;

 v.push_back(1);
 v.push_back(2);
 v.push_back(3);
 v.push_back(4);

 vector<int>::iterator itr = v.begin();
 vector<int>::iterator tem = v.begin();
 while(itr!=v.end())

 {
  cout<<"line1"<<*itr<<endl;
  tem=itr;
  itr++;
  cout<<"line2"<<*itr<<endl;
  v.erase(tem);
  cout<<"line3"<<*itr<<endl;
//但我在实际执行时出错提示“vector iterator not dereferencable”,查找原因个人认为:

                  //当调用erase()后itr和tem迭代器就失效了,变成了一野指针。所以要处理这种问题,关键是要                              // 解决调用erase()方法后,itr迭代器变成野指针的问题


 }
 printf("删除后的长度为%d",v.size());
 return 0;
}

我修改后代码为:

#include "stdafx.h"#include <vector>#include <iostream>using namespace std;int main(int argc, char* argv[]){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator itr = v.begin();vector<int>::iterator tem = v.begin();while(itr!=v.end()){cout<<"line1"<<*itr<<endl;tem=itr;itr++;if (itr == v.end()){break;}else{cout<<"line2"<<*itr<<endl;tem = v.erase(tem);//若把tem=去掉,会报错itr = tem + 1;//若这句去掉,也会报错if (itr == v.end())//没有这个判断,也会报错{break;}cout<<"line3"<<*itr<<endl;}}printf("删除后的长度为%d",v.size());system("pause");return 0;}


执行结果:

C++中Vector的删除操作
 
调试详解:

数据

1

2

3

4

未赋值

内存地址

B0

B4

B8

BC

C0

指针

begin

 

 

 

End

 

 

 

 

 

Last

执行第一个循环

tem=itr;

数据

1

2

3

4

未赋值

内存地址

B0

B4

B8

BC

C0

指针

begin

 

 

 

End

 

Tem itr

 

 

 

Last

itr++;

数据

1

2

3

4

未赋值

内存地址

B0

B4

B8

BC

C0

指针

begin

 

 

 

End

 

Tem

itr

 

 

Last

v.erase(tem);

数据

2

3

4

4

未赋值

内存地址

B0

B4

B8

BC

C0

指针

begin

 

 

Last

End

 

Tem

itr

 

 

 

 第二轮循环

tem=itr;

数据

2

3

4

4

未赋值

内存地址

B0

B4

B8

BC

C0

指针

begin

Tem

 

Last

End

 

 

itr

 

 

 

itr++;

数据

2

3

4

4

未赋值

内存地址

B0

B4

B8

BC

C0

指针

begin

Tem

 

Last

End

 

 

 

itr

 

 

v.erase(tem);

数据

2

4

4

4

未赋值

内存地址

B0

B4

B8

BC

C0

指针

begin

Tem

Last

 

End

 

 

 

itr

 

 

 

可见,erase操作之后,last指针前移,而end指针未变,被删除的元素后边的元素前移,last之后的元素保持不变(并未移除)。完成之后计算size是由last-begin得到的。

vector 的删除操作还是用如下方法:

it = v.erase(it);

即:

重新Iter迭代器指定下一个元素.

是直接赋删除元素的下一个迭代器给Iter

实现方法的代码如下:

  1. for(Iter = v1.begin(); Iter != v1.end(); Iter++) 
  2.   if(*Iter == 10) 
  3.   { 
  4.    Iter = v1.erase(Iter);//Iter为删除元素的下一个元素的迭代器
  5.   //即第一次这段语句后Iter 会是20,大家可以通过debug调试出来查看下数值
  6.   } 
  7.  
  8.   if(Iter == v1.end()) //要控制迭代器不能超过整个容器
  9.   { 
  10.    break;
  11.   } 
  12. }

remove or erase?
  很多人还用到过remove,但是对于很多人不能分清楚remove和erase的区别?

STL中remove()只是将待删除元素之后的元素移动到vector的前端,而不是删除。若要真正移除,需要搭配使用erase()。

vector中的remove的作用是将等于value的元素放到vector的尾部,但并不减少vector的size

vector中erase的作用是删除掉某个位置position或一段区域(begin, end)中的元素,减少其size。(转自别处)。



1 0
原创粉丝点击