码迷,mamicode.com
首页 > 编程语言 > 详细

【C++】C++中的迭代器

时间:2019-03-03 21:00:30      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:dig   class   修改   这一   pos   over   body   space   targe   

目录结构:

contents structure [-]

可以使用下标来访问string对象或vector对象的元素,还有另外一种更为通用的方式,这就是迭代器(iterator)。

迭代器类型类似于指针类型,也提供了对对象的间接访问。就迭代器而言,其对象便是容器中的元素或者string对象中的字符。使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另一个元素。迭代器有有效和无效之分,这一点和指针差不多。有效的迭代器指向某个元素,或者指向容器中尾元素的下一位置。

 

1.迭代器运算符

下面列举了一些迭代器支持的运算符:

运算符 说明
*iter 返回迭代器iter所指元素的引用
iter->men 解引用iter并获取改元素的名为men的成员,等价于(*iter).men
++iter 令iter指示容器中的下一个元素
--iter 令iter指示容器中的上一个元素
iter1 == iter2 判断两个迭代器是否相等,若两个迭代器指向同一个元素或者他们是同一个容器的尾后迭代器,则相等;反之,不相等。
iter1 != iter2 判断两个迭代器是否不相等。


下面使用迭代器把string中的第一个字母改成了大写形式:

string s("some string");
if(s.begin() != s.end()){//确保s不为空
    auto it = s.begin(); //it表示s第一个字符的大写字母
    *t = toupper(*t); //将当前字母改成大写形式
}


迭代器可以使用++运算符来从一个元素移动到另一个元素。从逻辑上讲,迭代器的跌增加和整数的递增类似,整数的递增是在整数值上加1,迭代器的递增怎是将迭代器“向前移动一个位置”。下面使用这个特性,也可以实现上面的效果:

for(auto it=s.begin(); it!=s.end() && !isspace(*it); ++it)
    *it = toupper(*it);


解引用迭代器可获得迭代器所指的对象,如果该对象的类型恰好是类,就有可能希望进一步访问它的成员(迭代器和指针类似,所以这一规则同样适用与指针)。
例如,对于一个由一串字符串组成的vector对象来说,想要检查其元素是否为空,令it是为iterator对象的迭代器,只需要检查it所指字符串是否为空就可以了,其代码如下:

(*it).empty(); //解引用it,然后调用结果对象的empty成员。
*it.empty();//错误:试图访问it名为empty()的成员,但it是一个迭代器,没有empty()的成员


为了简化这种操作,c++语言提供了箭头运算符(->)。箭头运算符把解引用和成员访问两个操作结合在一起:

it->empty(); //等同于(*it).empty();

案例:

//依次输出text的每一行直至遇到第一个空白符为止
vector<string> text{"abc","def"};
for(auto it=text.begin(); it!=text.end() && !it->empty(); ++it)//使用it->empty()判断所指是否为空
    cout << *it << endl;

指针和迭代器类似,也可以操作使用->运算符,例如:

string s1 = "a string", *p = &s1;
auto n = s1.size();//运行string对象s1的size成员
n = (*p).size();//运行p所值对象的size成员
n = p->size();//等价于(*p).size();

 

2.迭代器类型

通常来说,我们无需知道迭代器的精确类型,通常使用auto来表示。实际下,那么拥有迭代器的标准库类型使用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只能读字符,不能写字符

const_iterator和常量指针差不多,能读取但不能修改它所指的元素值。相反,iterator的对象可读可写。如果vector对象或string对象是一个常量,只能使用const_iterator; 如果vector对象或string对象不是常量,那么既可以使用iterator也能使用const_iterator。

 

3.begin和end运算符

begin和end返回的类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator;如果对象不是常量,返回iterator;

vector<int> v;
const vector<int> cv;
auto it1 = v.begin();//it1的类型是vector<int>::iterator
auto it2 = cv.begin();//it2的类型是vector<int>::const_iterator

有时候这种默认的行为不是我们想要的。为了便于专门得到const_iterator类型的返回值,c++11标准引入了两个新函数,分别是cbegin和cend:

auto it3 = v.cbegin(); // it3的类型是vector<int>::const_iterator
cbegin和cend的返回值类型都是vector<T>::const_iterator,cbegin返回迭代器指向首元素,cend返回的迭代器指向末元素的下一元素。

 

4.迭代器的算术运算

string和vector的迭代器提供了许多额外的算术运算符,下面是string和vector迭代器支持的迭代器算术运算符:

运算符 说明
iter + n 迭代器加上一个整数值仍得到一个迭代器,迭代器指示的新位置与原来相比向前移动了若干个元素。结果迭代器或者指示容器内一个元素,或者指示容器尾元素的下一位置
iter - n 迭代器减去一个整数值仍得到一个迭代器,迭代器指示的新位置与原来相比向后移动了若干个元素。结果迭代器或者指示容器内一个元素,或者指示容器尾元素的下以位置
iter += n 等同于 iter = iter + n
iter -= n 等同于 iter = iter - n
iter1 - iter2 两个迭代器相减的结果就是它们之间的距离,也就是说,将运算符右侧的迭代器向前移动若干个元素后就得到左侧的迭代器了。参与运算的两个迭代器必须指向同一个容器中的元素或者尾容器的下一个元素。
>,>=,<,<= 迭代器的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指位置之前,则说明前者小于后者。参与运算的两个迭代器必须指向同一个容器中的元素或者尾元素的下一元素。


下面我们使用迭代器运算来实现一个二分查找:

#include <iostream>
#include <vector>
using namespace std;

int main(){
vector<int> vec;//声明一个vector<int>容器

for(int i=0; i<100; i++)
 vec.push_back(i+1);//往容器中添加元素

auto beg = vec.begin();//得到指向容器首元素的迭代器
auto end = vec.end();//得到指向容器尾元素的迭代器
auto mid = beg + (end - beg)/2;//得到指向容器中间元素的迭代器

int target = 51;//搜索目标

while(beg <= end && *mid != target){
 if(target > *mid)
  beg = mid;
 else
  end = mid;
 mid = beg + (end - beg)/2;
}

if(beg <= end)
 cout << (mid-vec.begin()+1) << endl;//输出目标元素在容器中的位置
else
 cout << "not find"<< endl;//未找到目标元素

return 0;
}

 



【C++】C++中的迭代器

标签:dig   class   修改   这一   pos   over   body   space   targe   

原文地址:https://www.cnblogs.com/HDK2016/p/10467196.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!