迭代器分类

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++ 操作,还可以与整数进行算术运算。

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

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

编译器多态

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

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

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

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

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

针对输入迭代器的:

template<typename InputIterator, typename Distance>
void __advance(InputIterator& it, Distance n, input_iterator_tag)
{
while (n--) ++it;
}

针对前向迭代器的:

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

针对双向迭代器的:

template<typename InputIterator, typename Distance>
void __advance(InputIterator& it, Distance n, bidirectional_iterator_tag)
{
// 可以双向移动
if (n >= 0)
while (n--) ++it;
else
while (n++) --it;
}

针对随机访问迭代器的:

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

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

最新文章

  1. svm使用的一般步骤
  2. android优秀Github源码整理
  3. Security Configuration and Auditing Scripts for Oracle E-Business Suite (文档 ID 2069190.1)
  4. Spring Boot异常处理详解
  5. 通俗理解T检验和F检验
  6. IOSUIcontrol事件
  7. 批量插入使用SqlBulkCopy
  8. [Linux]学习笔记(1)
  9. 如何使用Eclipse API 提供 org.eclipse.wst.wsdl 要解决阅读WSDL档?
  10. Angular2的模块架构浅谈
  11. 90后的青春,定格在被淡忘的QQ空间里
  12. 基于Html5 Plus + Vue + Mui 移动App开发(三)-文件操作(读取、保存、更新数据)
  13. android 使用Canvas画箭头
  14. OpenResty入门之使用Lua扩展Nginx
  15. [PHP] 算法-原址排序数组使奇数位于偶数前面的PHP实现
  16. Python生成唯一id的方法
  17. Linux内核 GPIO操作部分API
  18. Android UIAutomator 定位
  19. UVa 11427 Expect the Expected (数学期望 + 概率DP)
  20. 前端Hack之XSS攻击个人学习笔记

热门文章

  1. 现代 CSS 指南 -- at-rule 规则扫盲
  2. 2022春每日一题:Day 22
  3. CheckBox 单选实现及取值
  4. python-py文件打包成exe可执行文件
  5. NLP实践!文本语法纠错模型实战,搭建你的贴身语法修改小助手 ⛵
  6. [.NET学习] EFCore学习之旅 -3 一些其他的迁移命令
  7. 写一个flutter程序
  8. 【PPT】NET Conf China 2022,主题:C#在iNeuOS工业互联网操作系统的开发及应用
  9. 【Shell案例】【取指定列的方式$5 p[6],双括号运算、awk、管道运算】8、统计所有进程占用内存大小的和
  10. Redis Lettuce长时间超时问题