迭代器:把标志控制的循环和计数控制的循环统一为一种控制,即迭代器控制,每一次迭代操作中对迭代器的修改就等价于修改标志或计数器。
容器迭代器:类似于数据库中的游标(cursor),屏蔽了底层存储空间的不连续性,在上层使容器元素维持一种“逻辑连续”的假象。工作逻辑如下:
不可把迭代器与void*和“基类指针”混淆:指针代表真正的内存地址,即对象在内存中的存储位置;迭代器则代表元素在容器中的相对位置。
STL把迭代器分为5类,它们都是类模板,具有通用性。如下表:
迭代器能力大小:输入迭代器,输出迭代器 < 前进迭代器 < 双向迭代器 < 随机访问迭代器
常用迭代器所属迭代器类别:
& Vector的迭代器为随机访问迭代器,因为它就是原始指针;
& list的迭代器是双向迭代器,因为list是双向链表;
& slist的迭代器是前进迭代器;
& deque的迭代器是随机访问迭代器;
& set/map的迭代器是双向迭代器;
......
迭代器使用建议:
1)尽量使用迭代器类型,而不是显示地使用指针。例如使用vector<int>::iterator,而不是int *,虽然他们等价。
2)只使用迭代器提供的标准操作,不要使用任何非标准操作,以避免STL版本更新的时候出现不兼容问题。
3)当不会改动容器中元素值的时候,使用const迭代器(const_iterator)。
迭代器失效的危险性:迭代器失效是指其指向容器中的某个或某些元素的存储发生了变化,使之成为无效迭代器,使用无效迭代器同时用无效指针一样危险。
解决迭代器失效问题有两种方式:1)在代用迭代器时重新获取迭代器;2)在修改容器前为其预留足够的空闲空间以避免存储空间重分配。
提示:顺序容器vector和string都可用reserve()和resize()来预留空间或调整它们的大小:reserve()用来保留(扩充)容量,它并不改变容器的有效元素个数;resize()则调整容器大小(size,有效元素个数),而且有时候会大容器的容量。当把这两个函数与assign()、insert()、push_back()、replace()及泛型算法搭配起来使用的时候,需要小心。
解决无效迭代器示例如下:
//迭代器失效程序
#include<iostream>
#include<vector>
using namespace std;
void main(){
vector<int> ages; //未预留空间
ages.push_back(2); //引起内存重分配
vector<int>::const_iterator p = ages.begin();
for(int i = 0; i<10; i++){
ages.push_back(5); //引起若干次内存重分配
}
cout<<"The first age:"<<*p<<endl; //p已经失效,危险访问
}
//解决方案1,重新获取迭代器
void main(){
//...
vector<int>::const_iterator p = ages.begin();
for(int i = 0;i<10; i++){
ages.push_back(5); //引起若干次内存重分配
}
p = ages.begin(); //重新获取迭代器
cout<<"The first age:"<<*p<<endl; //OK
}
转自:https://blog.csdn.net/open_gis/article/details/12058671?utm_source=copy