迭代器感觉上像是下标指示符的高级版本
vector和string都支持迭代器
一、试用迭代器
//由编译器决定b和e的类型
//b表示v的第一个元素,e表示v尾元素的下一位置
auto b=v.begin(), e=v.end(); //b和e的类型相同
二、迭代器运算符
运算符 | 作用 |
---|---|
*iter | 返回迭代器iter所指元素的引用 |
iter->men | 解引用iter并获取该元素的名为men的成员,等价于(*iter).men |
++iter | 指向下一个元素 |
–iter | 指向上一个元素 |
iter1==iter2 | 判断两个迭代器是否相等,若指向的是同一个元素 |
iter1!=iter2 | 或者同一个容器的尾后迭代器,则相等;反之,则不等 |
解引用迭代器,取结构体类型,可访问成员
end返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用的操作
在迭代器中大多数都没有定义<运算符,所以只有==和!=
代码如下(示例):
string s("some string");
//将第一个字母大写
if(s.begin()!=s.end()){
auto it=s.begin;
*it=toupper(*it);
}
//所有字符都大写
for(auto it=s.begin();it!=s.end();++it)
*it=toupper(*it);
三、迭代器类型
用iterator和const_iterator来表示迭代器的类型:
vector<int>::iterator it; //it能读写vector<int>的元素
string::iterator it2; //it2能读写string对象中的字符
vector<int>::const_iterator it3; //it3只能读元素,不能写元素
string::const_iterator it4; //it4只能读字符,不能写字符
如果vector对象或string对象是一个常量,只能使用const_iterator,
如果不是常量,则两个都可以用。
begin和end返回的具体类型也有对象是否是常量来决定
为了便于专门得到const_iterator类型的返回值,引入了 cbegin 和 cend
vector<int> v;
const vector<int> cv;
auto it1=v.begin(); //it1的类型是vector<int>::iterator
auto it2=cv.begin(); //it2的类型是vector<int>::const_iterator
auto it3=v.cbegin(); //it3的类型是vector<int>::const_iterator
注意:
但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。
四、迭代器运算
vector和string迭代器支持的运算 | |
---|---|
iter+n | 仍是一个迭代器,位置与原来相比向前移动了n个元素 |
iter-n | 同上,向后移动了n个元素 |
iter1+=n | 将iter1+n的结果赋给iter1 |
iter1-=n | 同上 |
iter1-iter2 | 参与运算的迭代器必须指向同一个容器中的元素或尾元素的 下一个位置,得出来的结果是两个迭代器之间的距离 其类型名为 difference_type 的带符号整型数 |
>,>=,<,<= | 如果所指位置在另一个迭代器所指之前,则小于,两个迭代器 要求同上 |
计算得到最接近v1中间元素的一个迭代器
auto mid = v.begin()+ v.end()/2 ;
用迭代器完成二分搜索
//已知,text有序,要找的是sought
auto b=text.begin(), e=text.end();
auto mid=text.begin()+(e-b)/2;
while(mid!=e && *mid!=sought){
if(sought < *mid)
e=mid;
else
b=mid=1;
mid=b+(e-b)/2;
//因为end指的是最后一个元素的后一个位置,所以用上面的
//而不用mid=(b+e)/2;
}
弱弱的问一下各路围观的大佬们:
为什么不可以用 it = touppre( it ) 啊,而是必须要加引用
关于迭代器的知识感觉有点懵,尤其是看了迭代器详解的那几篇文章之后,感觉更懵了QAQ。。
看了一下目录,还好书后边还有讲关于迭代器的,到时候学到那了再来回头看看吧,先一点点的往下学,可不能被迭代器给卡住。