当前位置:   article > 正文

[C++] 迭代器_c++迭代器

c++迭代器

目录

1. 概念

2. 类型

3. begin()和end()函数

3.1 cbegin()和cend()函数

3.2 rbegin()和rend()、crbegin()和crend()函数(不支持forward_list容器)

4. 迭代器的运算符

5. 迭代器的运算

6. 特殊的迭代器

6.1 插入迭代器

6.2 流迭代器

6.3 反向迭代器

6.4 移动迭代器 


1. 概念

迭代器(iterator):一种访问string对象以及容器中的元素的类型,不必拘泥于迭代器概念本身,或它到底是容器定义的迭代器类型还是一种对象,只需要理解它的操作是用来访问string对象以及容器里的元素的。其类似于指针

2. 类型

  1. vector<int> vint;
  2. vector<int>::iterator iit; //读写类型
  3. vector<int>::const_iterator icit; //只读类型
  4. vector<int>::reverse_iterator reit; //反向迭代器
  5. vector<int>::const_reverse_iterator reit; //反向只读迭代器

迭代器的类型是:

  1. 容器<类型>::iterator 迭代器名; ——读写类型
  2. 容器<类型>::const_iterator 迭代器名; ——只读类型
  3. 容器<类型>::reverse_iterator 迭代器名; ——反向迭代器
  4. 容器<类型>::const_reverse_iterator 迭代器名; ——反向只读迭代器

3. begin()和end()函数

有迭代器的类型同时拥有返回迭代器的成员函数:begin()和end()函数,它们的返回值就是迭代器类型iterator,所以我们可以使用begin()和end()函数来对容器和string对象的元素进行遍历。begin()指向的是容器的第一个元素,比如:vector就是下标为0的元素,end()指向的是最后一个元素的下一个元素,比如:vector里有10个元素,end()就是指向下标为10的元素,注意:这个元素的值是未知的,未定义的,只是用来表示遍历到了头而已。

  1. vector<int> vint;
  2. for(auto it=vint.begin();it!=ving.end();it++)
  3. {
  4. cout<<*it<<endl;
  5. }

为什么begin()要指向开头第一个元素,而end()要指向末尾最后一个元素的下一个呢?

因为:方便判断,左闭合范围

begin()==end():意味着容器里没有元素

begin()+1==end():意味着容器里只有一个元素

begin()+1<end():意味着容器里不止一个元素 

3.1 cbegin()和cend()函数

cbegin()函数和cend()函数是C++11的新标准,与begin()和end()的区别是,cbegin()和cend()返回的是const_iterator类型。就是用来,1.避免在循环体中做出了对元素修改的操作,2.当容器中所储对象是常量,则也只能使用这种类型

3.2 rbegin()和rend()、crbegin()和crend()函数(不支持forward_list容器

rbegin()和rend()返回的是reverse_iterator类型。同理还有crbegin()和crend()函数。注意:当迭代器是反向迭代器时,对迭代器进行的运算符操作也是反向的,如++操作,会返回指向容器的上一个元素。

4. 迭代器的运算符

*iterator获取迭代器所指容器的元素
iterator->item解引用,获取该元素名为item的成员,等价于(*iterator).item
++iterator下一个元素
--iterator上一个元素,forward_list不支持此操作
iterator1==iterator2判断两个迭代器是否在同一位置
iterator1!=iterator2判断两个迭代器是否在同一位置

5. 迭代器的运算

iterator+n迭代器向后移n个位置,n必须是整数
iterator-n迭代器向前移n个位置,n必须是整数
iterator+=n迭代器向后移n个位置,iterator=iterator+n,n必须是整数
iterator-=n迭代器向前移n个位置,n必须是整数
iterator1-iterator2看iterator1比iterator2领先几个位置,注意,iterator1必须大于iterator2,且返回类型是difference_type
>、>=、<、<=关系运算,比较两个迭代器的前后位置大小

注意:迭代器的运算里,没有iterator1+iterator2!!!,没有两个迭代器相加的运算。

6. 特殊的迭代器

头文件:#include<iterator>

6.1 插入迭代器

插入迭代器:这些迭代器被绑定在一个容器上,可用来向容器插入元素

三种插入迭代器:

        1.back_insert_iterator<_container>  (_container:如vector<string>):使用back_inserter函数创建一个对容器使用push_back进行插入的迭代器

        2.front_insert_iterator<_container> :使用front_inserter函数创建一个对容器使用push_front进行插入的迭代器

        3.insert_iterator<_container> :使用inserter函数创建一个使用insert进行插入的迭代器,接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素会插入到给定迭代器所指向的元素之前,注意:它第二个参数的位置是固定的,不是说在内存里的存储位置固定,是说它会一直指向它所指向的元素。

        此迭代器类型为: insert_iterator<_container>  (_container:如vector<string>)

注意:只有支持相应操作的容器才能使用对应的迭代器!

示例:

  1. list<int> lis={1,2,3,4};
  2. list<int> lis2;
  3. auto it=back_inserter(lis2);
  4. copy(lis.begin(),lis.end(),back_inserter(lis2)); //lis2:1,2,3,4
  5. copy(lis.begin(),lis.end(),front_inserter(lis2)); //lis2:4,3,2,1
  6. copy(lis.begin(),lis.end(),inserter(lis2,lis2.begin()); //lis2:1,2,3,4,因为lis2.begin()==lis2.end(),这里也可以看成指向end(),向end()前插入元素

6.2 流迭代器

流迭代器:流迭代器被绑定到I/O流上,它会将对应的流当作一个元素序列来处理,可用来遍历所关联的I/O流。

两种流迭代器:

        1.istream_iterator<type>  itratorname:输入流迭代器,输入流迭代器允许懒惰求值(第一次绑定的时候,标准库不保证迭代器立即从流中读值,标准库只保证在第一次解引用的之前,读取操作已经完成,一般来说,延迟读取和立即读取没有大区别,但是如果有两个绑定了相同流的不同的迭代器,那么他们两个的读取顺序就很重要了)

操作含义
istream_iterator<T> in(is);将输入流is绑定到in输入流迭代器上,迭代器读取类型为T的值
istream_iterator<T> end;一个空的输入流可以表示为流的尾后位置,eof。
in1 == in2、in1 != in2in1和in2必须读取相同类型。若都是尾后迭代器或绑定到相同的输入,两者就相等
*in读取相应的值
++in、in++有效,且遵循前置和后置递增的规则。

         2.ostream_iterator<type>  itratorname:输出流迭代器,输出流迭代器不允许为空,并不允许指向尾后位置。

操作含义
ostream_iterator<T> out(os);out将类型为T的值写到输出流os中
ostream_iterator<T> out(os,d);out将类型为T的值写出到输出流os中,并且每一个类型为T的值它后面都会添加一个字符串d,d是C风格的字符串(字符串字面值常量/指向"/0"的字符数组指针)
out == valout和val必须类型相等
*out、++out、out++不做任何操作,都返回out本身

示例:

  1. istream_iterator<int> itis(cin);
  2. istream_iterator<int> end;
  3. vector<int> vec(itis,end);
  4. sort(vec.begin(), vec.end());
  5. ostream_iterator<int> itos(cout);
  6. copy(vec.begin(), vec.end(), itos);
  7. //输入:0,2,4,1,3;
  8. //输出:0,1,2,3,4;

6.3 反向迭代器

注意:调用泛型算法的时候,如果算法里的迭代器是反向迭代器,那么其返回的迭代器也将是反向迭代器,这意味着后面如果有对这个迭代器的操作,那么将都会按着反向迭代器的操作来进行,这可能会导致预料之外的结果,比如:

  1. 序列vec:a b c d , e f g
  2. auto iterator=find(vec.rbegin(),vec.rend(),','); //反向查找第一个出现‘,’的位置
  3. cout<<string(vec.rbegin(),iterator)<<endl; //输出:gfe,error,因为我的预期结果是efg
  4. cout<<string(iterator,vec.end())<<endl; //error!因为此时iterator迭代器是反向迭代器,
  5. //对这个迭代器进行++操作时,是向vec.begin()靠拢的!
  6. cout<<string(iterator.base(),vec.end())<<endl; //true!base()函数可以将反向迭代器转换为普通迭代器,指向e字符

使用base()函数可以将反向迭代器转换为普通迭代器,但是其位置会有变化,base后的迭代器指向反向迭代器的所指元素的后一个元素(正序后一个)。 

6.4 移动迭代器 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/179609
推荐阅读
相关标签
  

闽ICP备14008679号