C++迭代器种类与编译期间多态
迭代器分类
C++ STL 中根据移动能力将迭代器分成了 5 类:
Input Iterator 输入迭代器,只支持 operator++ 操作。
Output Iterator 输出迭代器,只支持 operator++ 操作。
Forward Iterator 前向迭代器,只支持 operator++ 操作。
Bidirectional Iterator 双向迭代器,支持 operator-- 和 operator++ 操作。
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 时,编译器根据第三个参数(迭代器类型)选择最优模板。
C++迭代器种类与编译期间多态的更多相关文章
- C++编译期多态与运行期多态
前言 今日的C++不再是个单纯的"带类的C"语言,它已经发展成为一个多种次语言所组成的语言集合,其中泛型编程与基于它的STL是C++发展中最为出彩的那部分.在面向对象C++编程中, ...
- Java编译时多态和运行时多态
来源:https://blog.csdn.net/wendizhou/article/details/73733061 编译时多态:主要是方法的重载,通过参数列表的不同来区分不同的方法. 运行时多态: ...
- c++ 之 编译期多态&运行期多态
编译时多态:程序运行前发生的事件 —— 函数重载.运算符重载 .模板 ——静态绑定 运行时多态:程序运行时发生的事件 —— 虚函数机制——动态绑定 template<typename T> ...
- 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)
在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...
- 读书笔记_Effective_C++_条款四十一:了解隐式接口和编译期多态
从本条款开始,就进入了全书的第七部分:模板与泛型编程.模板与泛型在C++中是非常重要的部分,还记得本书第一章时,把C++视为一个联邦,它由四个州政府组成,其中一个政府就是模板与泛型了. 本条款是一个介 ...
- c#中运行时编译时 多态
c#中运行时编译时 多态 public class aa { } public class bb:aa { } public class cc { public static void Main( ...
- 读书笔记 effective c++ Item 41 理解隐式接口和编译期多态
1. 显示接口和运行时多态 面向对象编程的世界围绕着显式接口和运行时多态.举个例子,考虑下面的类(无意义的类), class Widget { public: Widget(); virtual ~W ...
- c++中如何定义编译期间常量,即这个常量可以用于定义数组下标
在c++中,类里面的成员变量不仅仅可以被const修饰,还可以被static const修饰,此时一个内建类型(如int ,char ,long等)的static const 可以看做是一个编译期间的 ...
- Effective C++ Item 41 了解隐式接口和编译期多态
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:class 和 templates 都支持接口和多态. 对 classes 而言接口是 ...
- Effective C++ -----条款41:了解隐式接口和编译期多态
classes和templates都支持接口(interface)和多态(polymorphism). 对classes而言接口是显式的(explicit),以函数签名为中心.多态则是通过virtua ...
随机推荐
- ArchLinux安装手册(2022-10-01)
准备工作 镜像下载:北京外国语大学镜像 使用ventoy做启动盘: (1) ventoy下载:github下载地址 (2) 解压运行下载好的ventoy,设备选择准备好的U盘(会清空),然后选择安装即 ...
- python(27)反射机制
1. 什么是反射? 它的核心本质其实就是基于字符串的事件驱动,通过字符串的形式去操作对象的属性或者方法 2. 反射的优点 一个概念被提出来,就是要明白它的优点有哪些,这样我们才能知道为什么要使用反射. ...
- laravel的_token传值 ; header中传_token
laravel框架中只要是涉及到post传值都需要传 _token ,这是框架中为了防止crsf攻击所做的安全措施,那么我们用到ajax中的post 方式传值时,也需要在所传数据中添加一个_token ...
- 【第6篇】AI语音测试简介
1.4 AI语音测试简介 AI语音测试是针对人工智能语音交互的测试,人工智能语音交互一般包含语音识别技术(ASR).自然语言处理技术(NLP)和语音合成技术(TTS)等3大部分,通俗地来讲AI语音测试 ...
- WINDOWS下对NIGNX日志文件进行限制
首先接到这个任务,发现nginx的日志限制更多的都是在Linux下做的,找了半天,也没找到能直接通过nginx.conf更改体现到日志限制上的. 最后决定直接通过bat脚本,来对nginx的日志进行分 ...
- 关于在linux上vm virtualbox读取不到U盘问题的解决
1.设置usb2.0模式 如果你没安装拓展插件的话,调成usb2.0就会出现无效的配置这个提示,并且启动虚拟机会报 Implementation of the USB 2.0 controller n ...
- 各类数据库写入Webhsell总结
1.MySQL写入WebShell 1.1写入条件 数据库的当前用户为ROOT或拥有FILE权限: 知道网站目录的绝对路径: PHP的GPC参数为off状态: MySQL中的secure_file_p ...
- 【Shell案例】【awk map计数&sort按指定列排序】9、统计每个单词出现的个数
描述写一个 bash脚本以统计一个文本文件 nowcoder.txt 中每个单词出现的个数. 为了简单起见,你可以假设:nowcoder.txt只包括小写字母和空格.每个单词只由小写字母组成.单词间由 ...
- 【每日一题】【List与Array互转】【工具类的使用】2021年12月10日-56. 合并区间
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] .请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入 ...
- Qt网络编程-书接上文,浅谈TCP文件收发,以及心跳包
qt网络编程-书接上文,浅谈文件收发 上文Qt网络编程-从0到多线程编程中谈到 在qt中的qtcpsocket通讯的用法,接下来浅谈一下关于tcp通讯的实际应用,当然了由于是浅谈,也不能保证其功能的完 ...