首页 > 编程语言 >C++迭代器种类与编译期间多态

C++迭代器种类与编译期间多态

时间:2023-02-02 22:23:23浏览次数:37  
标签:__ advance 迭代 iterator ++ 多态 C++ --

迭代器分类

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 时,编译器根据第三个参数(迭代器类型)选择最优模板。

标签:__,advance,迭代,iterator,++,多态,C++,--
From: https://www.cnblogs.com/zwjason/p/17087594.html

相关文章

  • TensorFlow中,对于1个batch中有多个样本,迭代一次,具体是如何执行的
    TensorFlow中,对于1个batch中有多个样本,迭代一次,具体是如何执行的total=旧参下计算更新值1+旧参下计算更新值2+…+旧参下计算更新值500新参数=旧参数+totalRef:​​......
  • c++语言程序设计第一章笔记
    在最开始,老师就向我们介绍了计算机语言的发展历史。也就是先前,在计算机刚开始发展的时候,那时候计算机语言与自然语言之间具有很大的鸿沟(计算机只能读懂二进制的0和1),比机器......
  • 动态修改Azure DevOps区域路径或迭代路径的继承权限(Inhertiance)
    Contents1.场景描述2.解决方案2.1更改继承的接口:ChangeInhertiance2.2获取区域路径的接口:ClassificationNodes1.场景描述客户使用工作项模板,定制了一个设计变更流程,需......
  • 浅谈python容器、迭代器与生成器
    前言:for...in...循环时,与while不同的是,for可以自动访问容器中的下一个元素,这是为什么呢?#用while循环访问列表容器iter_a=iter(a)whileTrue:try:print(ne......
  • 关于C++的词汇统计
    提问: 输入输出怎么写,希望大家帮忙补充。C++词汇统计把所有单词/短语汇总在一起,找出出现次数最多的那个。输入是一行,为所有单词,由空格隔开。最多有100000个单词。输出一个......
  • C++ 处理字符串编码问题
    #include<iostream>#include<locale>#include<codecvt>std::stringUnicodeToUTF8(conststd::wstring&wstr){std::stringret;try{std::wst......
  • 代码随想录算法训练营Day2|977有序数组的平方 209.长度最小的子数组 59螺旋矩阵Ⅱ(C++)
     LeetCode刷题,代码随想录算法训练营Day2977.有序数组的平方 题目链接:977.有序数组的平方 题目思路:关键在于双指针思想的应用输入:nums=[-4,-1,0,3,10]输出:[0......
  • C++之智能指针
    一、为什么需要智能指针?如果在div()输入的b==0,那么就会抛出一个异常,被main()捕获,但是在Func()中new申请的资源就会因没释放而发生泄露问题,这是一种异常安全问......
  • C++ 树进阶系列之线段树和它的延迟更新
    1.前言线段树和树状数组有相似之处,可以用于解决区间类型的问题。但两者又各个千秋,树状数组本质是数组,有着树的形,可以借用树的一些概念。线段树是典型的二叉树结构,无论神......
  • C++中char*与string转换
    (1)char*转换为string:直接赋值即可chara[1024]="abcdefg";stringmm=a;(2)求char*(不包含\0)以及string的长度:strlen()函数cout<<"a.size:"<<strlen(a)<<endl;......