一. 什么是迭代器?
- 迭代器是STL中行为类似指针的设计模式,它可以提供了一种对容器中的对象的访问方法;并且它没有暴露容器中内部的表述方式。
- 例如STL中的map和set,它们的底层是一颗红黑树(一种平衡树),而当你用迭代器去对他们进行访问时,原本在红黑树中的二叉树结构却能转换成一种线性结构的访问方式,如上述例子。
- 也就是说,迭代器提供了一种一般化的方法对顺序或关联容器类型中的每个元素进行连续访问。
- 可见,迭代器既能对容器中的对象进行访问,又能将容器的结构隐藏起来,达到封装的效果。
- 所有容器有含有其各自的迭代器型别(iterator types),所以当你使用一般的容器迭代器时,并不需要含入专门的头文件。不过有几种特别的迭代器,例如逆向迭代器,被定义于<iterator>中。
- 迭代器可以看做一种智能指针,他会重载*和->运算符。但是它并不一定具备指针的所有运算符:p++,p--,p+n,p-n,p[n],p1-p2,p1<p2,p1!=p2。有可能它只提供一部分,比如:p++,p--,p1!=p2。
- STL强数据容器与算法分开,而迭代器又作为胶着剂将其撮合在一起。几乎STL提供的所有算法都是通过迭代器存取元素序列进行工作的,每一个容器都定义了其本身所专有的迭代器,用以存取容器中的元素。
- 每种容器还定义了一种名为const_iterator的类型。该类型的迭代器只能读取容器中的元素,不能用于改变其值。
- 由于一些对容器的操作如删除元素或移动元素等会修改容器的内在状态,这会使得原本指向被移动元素的迭代器失效,也可能同时使其他迭代器失效。使用无效的迭代器是没有定义的,可能会导致和使用悬垂指针相同的问题。所以在使用迭代器编写程序时,需要特别留意哪些操作会使迭代器失效。使用无效迭代器会导致严重的运行时错误。
二. 怎么用迭代器?
1. 定义和初始化
- 每种容器都定义了自己的迭代器类型,如vector:
vector<int>::iterator iter; //定义一个名为iter的变量
- 每种容器都定义了一对名为begin和end的函数,用于返回迭代器。下面对迭代器进行初始化操作:
vector<int> ivec;
vector<int>::iterator iter1=ivec.bengin(); //将迭代器iter1初始化为指向ivec容器的第一个元素
vector<int>::iterator iter2=ivec.end(); //将迭代器iter2初始化为指向ivec容器的最后一个元素的下一个位置
- 注意end并不指向容器的任何元素,而是指向容器的最后元素的下一位置,称为超出末端迭代器。如果vector为空,则begin返回的迭代器和end返回的迭代器相同。一旦向上面这样定义和初始化,就相当于把该迭代器和容器进行了某种关联,就像把一个指针初始化为指向某一空间地址一样。
2. 常用操作
*iter //对iter进行解引用,返回迭代器iter指向的元素的引用
iter->men //对iter进行解引用,获取指定元素中名为men的成员。等效于(*iter).men
++iter //给iter加1,使其指向容器的下一个元素
iter++
--iter //给iter减1,使其指向容器的前一个元素
iter--
iter1==iter2 //比较两个迭代器是否相等,当它们指向同一个容器的同一个元素或者都指向同同一个容器的超出末端的下一个位置时,它们相等
iter1!=iter2
- 例如,假设已经声明一个vector<int>的ivec容器,下面用迭代器来遍历ivec容器,把其每个元素重置为0:
for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
*iter=0;
参考文章:
【STL】迭代器
STL中的Iterator
C++迭代器的使用和操作总结