迭代器分类

C++ STL 中根据移动能力将迭代器分成了 5 类:

  1. Input Iterator 输入迭代器,只支持 operator++ 操作。

  2. Output Iterator 输出迭代器,只支持 operator++ 操作。

  3. Forward Iterator 前向迭代器,只支持 operator++ 操作。

  4. Bidirectional Iterator 双向迭代器,支持 operator-- 和 operator++ 操作。

  5. Random Access Iterator 随机访问迭代器,不仅支持 operator-- 和 operator++ 操作,还可以与整数进行算术运算。

  1. int main()
  2. {
  3. // 1.输入迭代器, 只能读缓冲区
  4. // 这样会直接进入读取状态一直读取int, 直到状态出错或遇到EOF
  5. // 比如输入了非数字, ctrl + d等等
  6. istream_iterator<int> initer(cin);
  7. int x = *initer; // 从缓冲区读取第一个数到变量中
  8. // 2.输出迭代器, 只能写到某个地方
  9. ostream_iterator<int> oiter(cout, " "); // 绑定到标准输出, 分隔符为空格字符串
  10. vector<int> v{1, 2, 3, 4};
  11. copy(v.begin(), v.end(), oiter); // 输出1 2 3 4
  12. cout << endl;
  13. // 3.前向迭代器, unordered_xxx系列的关联式容器的迭代器就是这个类型的
  14. // 大部分能读能写, set 系列由于键值合一, 不能够写
  15. // map 中 key 不可更改, value 可以
  16. unordered_map<int, char> m{{1, 'a'}, {2, 'b'}};
  17. unordered_map<int, char>::iterator mit = m.begin();
  18. while (mit != m.end()) {
  19. mit->second = 'c'; // 可以修改 value
  20. ++mit; // 不支持 operator--
  21. }
  22. // 4.双向迭代器, list 的迭代器就是该类型的
  23. list<int> l{1, 2, 3};
  24. list<int>::iterator lit = l.begin(); // 指向 1
  25. ++lit; // 指向 2
  26. --lit; // 回到 1
  27. *lit = 666; // 更改
  28. // 5.随机访问迭代器, vector 和 deque 的迭代器就是该类型的
  29. // 例如输出 vecor 的最后一个元素
  30. vector<int>::iterator vit = v.begin();
  31. cout << *(vit + v.size() - 1) << endl; // 支持与整数运算
  32. return 0;
  33. }

忽略了头文件,自行添加。

编译器多态

C++ STL 中很多算法会根据迭代器参数的类型来选择最优的实现方法,以 advance 为例,它的作用是将给定的迭代器移动指定步数,实现如下:

  1. template<typename InputIterator, typename Distance>
  2. void advance(InputIterator& it, Distance n)
  3. {
  4. // concept requirements -- taken care of in __advance
  5. typename iterator_traits<InputIterator>::difference_type d = n;
  6. std::__advance(i, d, std::__iterator_category(it));
  7. }

可以看到它内部转调了 std::__advance,注意到它的第三个参数 std::__iterator_category(it)

该方法根据传入的迭代器返回一个迭代器类型对象,一共 5 种,迭代器类型命名类似于 xxx_iterator_tag。

然后std::__advance共有如下版本:

针对输入迭代器的:

  1. template<typename InputIterator, typename Distance>
  2. void __advance(InputIterator& it, Distance n, input_iterator_tag)
  3. {
  4. while (n--) ++it;
  5. }

针对前向迭代器的:

  1. template<typename InputIterator, typename Distance>
  2. void __advance(InputIterator& it, Distance n, forward_iterator_tag)
  3. {
  4. __advance(it, n, input_iterator_tag()); // 直接转调
  5. }

针对双向迭代器的:

  1. template<typename InputIterator, typename Distance>
  2. void __advance(InputIterator& it, Distance n, bidirectional_iterator_tag)
  3. {
  4. // 可以双向移动
  5. if (n >= 0)
  6. while (n--) ++it;
  7. else
  8. while (n++) --it;
  9. }

针对随机访问迭代器的:

  1. template<typename InputIterator, typename Distance>
  2. void __advance(InputIterator& it, Distance n, random_access_iterator_tag)
  3. {
  4. it += n; // 直接加, 跳着走, 爽得一批
  5. }

当我们调用 advance 时,编译器根据第三个参数(迭代器类型)选择最优模板。

C++迭代器种类与编译期间多态的更多相关文章

  1. C++编译期多态与运行期多态

    前言 今日的C++不再是个单纯的"带类的C"语言,它已经发展成为一个多种次语言所组成的语言集合,其中泛型编程与基于它的STL是C++发展中最为出彩的那部分.在面向对象C++编程中, ...

  2. Java编译时多态和运行时多态

    来源:https://blog.csdn.net/wendizhou/article/details/73733061 编译时多态:主要是方法的重载,通过参数列表的不同来区分不同的方法. 运行时多态: ...

  3. c++ 之 编译期多态&运行期多态

    编译时多态:程序运行前发生的事件 —— 函数重载.运算符重载 .模板  ——静态绑定 运行时多态:程序运行时发生的事件 —— 虚函数机制——动态绑定 template<typename T> ...

  4. 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  5. 读书笔记_Effective_C++_条款四十一:了解隐式接口和编译期多态

    从本条款开始,就进入了全书的第七部分:模板与泛型编程.模板与泛型在C++中是非常重要的部分,还记得本书第一章时,把C++视为一个联邦,它由四个州政府组成,其中一个政府就是模板与泛型了. 本条款是一个介 ...

  6. c#中运行时编译时 多态

    c#中运行时编译时 多态   public class aa { } public class bb:aa { } public class cc { public static void Main( ...

  7. 读书笔记 effective c++ Item 41 理解隐式接口和编译期多态

    1. 显示接口和运行时多态 面向对象编程的世界围绕着显式接口和运行时多态.举个例子,考虑下面的类(无意义的类), class Widget { public: Widget(); virtual ~W ...

  8. c++中如何定义编译期间常量,即这个常量可以用于定义数组下标

    在c++中,类里面的成员变量不仅仅可以被const修饰,还可以被static const修饰,此时一个内建类型(如int ,char ,long等)的static const 可以看做是一个编译期间的 ...

  9. Effective C++ Item 41 了解隐式接口和编译期多态

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:class 和 templates 都支持接口和多态. 对 classes 而言接口是 ...

  10. Effective C++ -----条款41:了解隐式接口和编译期多态

    classes和templates都支持接口(interface)和多态(polymorphism). 对classes而言接口是显式的(explicit),以函数签名为中心.多态则是通过virtua ...

随机推荐

  1. 将C#的bitmap格式转换为Halcon的图像格式

    /// <summary> /// Bitmap转HObject灰度图 /// </summary> /// <param name="bmp"> ...

  2. 2022-11-04 Acwing每日一题

    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...

  3. Pthread 并发编程(三)——深入理解线程取消机制

    Pthread 并发编程(三)--深入理解线程取消机制 基本介绍 线程取消机制是 pthread 给我们提供的一种用于取消线程执行的一种机制,这种机制是在线程内部实现的,仅仅能够在共享内存的多线程程序 ...

  4. Java开发学习(四十二)----MyBatisPlus查询语句之条件查询

    一.条件查询的类 MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合. 这个我们在前面都有见过,比如查询所有和分页查询的时候,都有看到过一个Wrapper类, ...

  5. 对Java Web中WEB-INF目录的理解以及访问方法

    事情发生 在上个暑假第一次写Java web大项目的时候,对于目录管理及分配没有任何经验,就想着清晰明了. 后端servlet是用maven进行构建的,所以在目录上没有碰到什么大问题. 用idea进行 ...

  6. easui datagrid 行获取后台sql所有数据:支持行chockbox多选,输出选中行任意属性;支持点击表中属性实现跳转;支持分页。

    easyUI datagrid 代码: <table id="tabgrid20170726191838251403" class="easyui-datagrid ...

  7. js文字无限循环向上滚动

    html代码 <div id="scroll"> <div id="con1"> <p style="color: re ...

  8. 通过启动脚本控制PHP-FPM开关

    vi /etc/init.d/php-fpm 复制粘贴以下内容: #! /bin/sh# Comments to support chkconfig on CentOS# chkconfig: 234 ...

  9. 【Spring系列】- Spring循环依赖

    Spring循环依赖 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目录 Spring循 ...

  10. MongoDB安全加固,防止数据库攻击删除勒索威胁

    前言: 今天发现前段时间自己搭建的一个系统的MongoDB数据找不到了,觉得很奇妙,然后登上MongoDB数据库发现多了一个名为READ__ME_TO_RECOVER_YOUR_DATA的数据库,里面 ...