迭代器是什么
迭代器类型类似于指针类型,也提供了对对象的间接访问。就迭代器而言,其对象便是容器中的元素或者string对象中的字符。使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另一个元素。迭代器有有效和无效之分,这一点和指针差不多。有效的迭代器指向某个元素,或者指向容器中尾元素的下一位置。
我们可以把迭代器理解为指针 但它又不同于指针 。比如我们用sizeof来测它所占的内存,它并不占四个字节。
vector<int> :: iterator it;
cout<<sizoef(it)<<endl;
可以看到它并不是一个指针的大小。
那我们平时说的迭代器失效是怎么回事呢?
像我们对vector deque 容器进行增加或者是删除元素时,因为vector deque是内存连续的一段空间。当我们进行删除时,删除元素后所有元素都要往前挪一个位置,增加元素时要往后挪一个位置。其后就导致迭代器失效。
#include<iostream>
#include<vector>
using namespace std;
void Test(){
vector<int>vec;
for(int i=0;i<10;i++){
vec.push_back(i);
}
vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++){
if(*it%2==0){
vec.erase(it);//这里会发生迭代器失效
}
}
for(it=vec.begin();it!=vec.end();it++){
cout<<*it<<" ";
}
}
int main(){
Test();
return 0;
}
这个代码就会出现错误
已经失效的迭代器不能进行++操作,所以程序中断了。不过vector的erase操作可以返回下一个有效的迭代器,所以只要我们每次执行删除操作的时候,将下一个有效迭代器返回就可以顺利执行后续操作了,代码修改如下:
for (it = vec.begin(); it != vec.end(); )
{
if (*it%2==0)
{
it = vec.erase(it);//更新迭代器it
}
it++;
这样删除后it指向的元素后,返回的是下一个元素的迭代器,这个迭代器是vector内存调整过后新的有效的迭代器。此时就可以进行正确的删除与访问操作了。上面只是举了删除元素造成的vector迭代器失效问题,对于vector的插入元素也可以同理得到验证,这里就不再进行举例了。
vector迭代器失效问题:
1.当进行erase方法时,指向删除节点的迭代器全部失效,指向
节点之后的迭代器也失效。
2.当进行push_back()方法时,end操作返回的迭代器肯定失效。
3.当插入insert()方法时,插入位置后的迭代器全部失效。
deque迭代器失效问题:
1.对于deque来说 ,插入时除了首尾位置,都会导致迭代器,引用,指针失效。如果在首尾位置插入,迭代器失效,指针引用不会失效。
2.如果在首尾之外的任何位置删除元素,除删除元素外的所有元素迭代器都失效。
3.在受尾删除元素只会使首尾元素的迭代器失效。
另外,对于关联容器(如map, set,multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)的方式删除迭代器。