面试之快速学习STL-迭代适配器

这篇具有很好参考价值的文章主要介绍了面试之快速学习STL-迭代适配器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先放一张大图

参考:http://c.biancheng.net/view/7255.html
面试之快速学习STL-迭代适配器,面试之快速学习STL,面试,学习,c++

1. 反向迭代器

例子:

    std::list<int> values{1,2,3,4,5};
    auto start_it = values.rbegin();
    const auto end_it = values.rend();
    //start_it end_it std::reverse_iterator<std::list<int>>::iterator
    while (start_it != end_it) {
        std::cout << *start_it << std::endl;
        ++start_it;
    }
    /*
     5
     4
     3
     2
     1
     */
  1. 想使用反向迭代器实现逆序遍历容器,则该容器的迭代器类型必须是双向迭代器或者随机访问迭代器。
    面试之快速学习STL-迭代适配器,面试之快速学习STL,面试,学习,c++
  2. 常见操作
    面试之快速学习STL-迭代适配器,面试之快速学习STL,面试,学习,c++
    std::vector<int> values{1,2,3,4,5};
    auto r_start_it = values.rbegin();
    const auto end_it = values.rend();
    //r_start_it end_it std::reverse_iterator<std::list<int>>::iterator
    while (r_start_it != end_it) {
        std::cout << *r_start_it << std::endl;
        ++r_start_it;
    }
    /*
     5
     4
     3
     2
     1
     */
    
    r_start_it = values.rbegin();
    std::cout << "r_start_it + 3 = " << *(r_start_it + 3)<< std::endl;
    std::cout << "r_start_it[3] = " << r_start_it[3] << std::endl;
    
  1. 注意这里不能用std::list,因为它是双向迭代器, +3的操作需要随机访问迭代器。故联想到std::list排序只能使用list提供的 sort 接口,而不能使用algorithm 提供的 sort 接口,因为链表的物理地址不连续,迭代器为双向迭代器,不支持 + - 操作,而算法库中的 sort 接口需要支撑 + - 的随机迭代器;

2. 插入迭代器适配器

面试之快速学习STL-迭代适配器,面试之快速学习STL,面试,学习,c++

感觉没啥好讲的,看看代码:

#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main() {
    //创建一个 vector 容器
    std::vector<int> foo;
    //创建一个可向 foo 容器尾部添加新元素的迭代器
    std::back_insert_iterator< std::vector<int> > back_it(foo);
    //将 5 插入到 foo 的末尾
    back_it = 5;
    //将 4 插入到当前 foo 的末尾
    back_it = 4;
    //将 3 插入到当前 foo 的末尾
    back_it = 3;
    //将 6 插入到当前 foo 的末尾
    back_it = 6;
    //输出 foo 容器中的元素
    for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it)
        std::cout << *it << ' ';
    return 0;
    /*
    5 4 3 6
    */
}
  1. 每次插入新元素时,该元素都会插入到当前 foo 容器的末尾。换句话说,程序中 11-17 行的每个赋值语句,都可以分解为以下这 2 行代码:

//pos表示指向容器尾部的迭代器,value 表示要插入的元素
pos = foo.insert(pos,value);
++pos;

3. istream_iterator和ostream_iterator

原理源码:原理

  1. 自己理解:istream_iterator是重载了++操作符然后调用的是read(); ostream_iterator重载 = 操作符,做输出操作
#include <iostream>
#include <thread>
#include <vector>
#include <numeric>
#include <algorithm>
#include <cstring>
#include <deque>
#include <iterator>
using namespace std;
 
int main()
{
	deque<int> id;
 
	istream_iterator<int> intie(cin),eos;                     //开始触发一次输入   
	copy(intie, eos, inserter(id, id.begin()));               //迭代器类型为InputIterator,所以这里调用copy的时候采用*result = *first;版本,会使用重载类型 ,那么就会转换为插入操作      
															  //其中++first会继续调用下一个,然后重载为新的输入
	
	ostream_iterator<int> outie(cout, " ");                  //deque的迭代器类型为random_access_iterator,也会是 *result = *first;调用赋值操作  result++操作,返回本身,不影响后面的输出操作
	copy(id.begin(), id.end(), outie);                       //将=操作,转换为输出操作
	cout << endl;
	
	system("pause");
}

3. 移动迭代器


    std::vector<std::string> v1{ "haha", "xixi" };
        //调用移动构造函数
    std::vector<std::string> v2(make_move_iterator(v1.begin()), make_move_iterator(v1.end()));
    std::cout << "v1 : " << std::endl;
    for (auto record : v1)
        std::cout << record << std::endl;
    std::cout << "v2 : " << std::endl;
    for (auto record : v2)
        std::cout << record << std::endl;
        /*
     v1 :

     v2 : haha
     xixi
     */

没啥好说的,就是每个值调用移动构造函数make_move_iterator

4. advance()函数用法详解

template <class InputIterator, class Distance>
void advance (InputIterator& it, Distance n);

  1. 根据 it 类型是否为随机访问迭代器,advance() 函数底层采用了不同的实现机制:
    当 it 为随机访问迭代器时,由于该类型迭代器支持 p+n 或者 p-n(其中 p 就是一个随机访问迭代器)运算,advance() 函数底层采用的就是 it+n 操作实现的;
    当 it 为其他类型迭代器时,它们仅支持进行 ++ 或者 – 运算,这种情况下,advance() 函数底层是通过重复执行 n 个 ++ 或者 – 操作实现的。

#include <iostream>     // std::cout
#include <iterator>     // std::advance
#include <forward_list>
using namespace std;
int main() {
    //创建一个 forward_list 容器
    forward_list<int> mylist{1,2,3,4};
    //it为前向迭代器,其指向 mylist 容器中第一个元素
    forward_list<int>::iterator it = mylist.begin();
    //借助 advance() 函数将 it 迭代器前进 2 个位置
    advance(it, 2);
    cout << "*it = " << *it;
    return 0;
}

注意: 此程序中,由于 it 为前向迭代器,其只能进行 ++ 操作,即只能前进(右移),所以 advance() 函数的第 2 个参数只能为正数。

5. distance()函数用法详解

template
typename iterator_traits::difference_type distance (InputIterator first, InputIterator last);文章来源地址https://www.toymoban.com/news/detail-673098.html

  1. first 和 last 的迭代器类型,直接决定了 distance() 函数底层的实现机制:
    当 first 和 last 为随机访问迭代器时,distance() 底层直接采用 last - first 求得 [first, last) 范围内包含元素的个数,其时间复杂度为O(1)常数阶;
    当 first 和 last 为非随机访问迭代器时,**distance() 底层通过不断执行 ++first(或者 first++)直到 first==last,**由此来获取 [first, last) 范围内包含元素的个数,其时间复杂度为O(n)线性阶。
#include <iostream>     // std::cout
#include <iterator>     // std::distance
#include <list>         // std::list
using namespace std;

int main() {
    //创建一个空 list 容器
    list<int> mylist;
    //向空 list 容器中添加元素 0~9
    for (int i = 0; i < 10; i++) {
        mylist.push_back(i);
    }
    //指定 2 个双向迭代器,用于执行某个区间
    list<int>::iterator first = mylist.begin();//指向元素 0
    list<int>::iterator last = mylist.end();//指向元素 9 之后的位置
    //获取 [first,last) 范围内包含元素的个数
    cout << "distance() = " << distance(first, last);
    return 0;
}

到了这里,关于面试之快速学习STL-迭代适配器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STL】顺序容器与容器适配器

    给出以下顺序容器表: 顺序容器类型 作用 vector 可变大小的数组,支持快速访问,除尾元素的插入或者删除很慢 string 与vector相似,只不过专门用来存字符 list 双向链表。只能双向顺序访问,插入删除的效率都很高 forward_list 单向链表。只能单向顺序访问,插入删除的效率都

    2024年04月14日
    浏览(31)
  • 【C++进阶之路】适配器、反向迭代器、仿函数

    我们先来笼统的介绍一下今天的三个内容。 适配器——简单的理解就是 复用 ,用已经实现的轮子,来继续实现某种功能。 反向迭代器——原理很简单,就是 对称+复用 (已经造好的正向迭代器) 仿函数—— 与函数用法相同 的类,用于排序,比如大堆,小堆,升序,降序。

    2024年02月16日
    浏览(40)
  • C++ STL学习之【容器适配器】

    ✨个人主页: 北 海 🎉所属专栏: C++修行之路 🎊每篇一句: 图片来源 A year from now you may wish you had started today. 明年今日,你会希望此时此刻的自己已经开始行动了。 适配器(配接器)是 STL 中的六大组件之一,扮演着轴承、转换器的角色,使得 STL 中组件的使用更为灵活,

    2023年04月22日
    浏览(56)
  • STL: 容器适配器stack 与 queue

      目录 1.容器适配器 1.1 STL标准库中stack和queue的底层结构 1.2 deque的简单介绍(了解) 1.2.1 deque的原理介绍 1.2.2 deque的缺陷 1.2.3 为什么选择deque作为stack和queue的底层默认容器 2. stack的介绍和使用 2.1 stack的介绍  2.2 stack的使用 2.3 利用deque模拟实现stack 3.queue的介绍和使用 3.1 queue的

    2024年02月05日
    浏览(45)
  • 22 标准模板库STL之容器适配器

    概述         提到适配器,我们的第一印象是想到设计模式中的适配器模式:将一个类的接口转化为另一个类的接口,使原本不兼容而不能合作的两个类,可以一起工作。STL中的容器适配器与此类似,是一个封装了序列容器的类模板,它在一般序列容器的基础上提供了一

    2024年02月05日
    浏览(39)
  • STL stack,queue,deque以及适配器

    下面是stack库中的接口函数,有了前面的基础,我们可以根据函数名得知函数的作用 函数 说明 stack() 构造空栈 empty() 判断栈是否为空 size() 返回栈中元素个数 top 返回栈顶元素 push() 将值从栈顶压入栈内 pop() 在栈顶出栈 栈其实就是一种特殊的 vector ,因此可以使用 vector 模拟实

    2024年02月10日
    浏览(38)
  • 【C++】STL之容器适配器——使用deque适配stack和queue

    个人主页:🍝在肯德基吃麻辣烫 分享一句喜欢的话:热烈的火焰,冰封在最沉默的火山深处。 本文章主要介绍容器适配器的功能,以及一个适配的场景。 容器适配器,按字面意思理解的话,就是用来对一个容器进行匹配的。在C++STL中,容器有:vector,list,deque,map,set等。

    2024年02月16日
    浏览(54)
  • 【C++】STL 算法 ⑩ ( 函数适配器 | 函数适配器概念 | 函数适配器分类 | 函数适配器辅助函数 | std::bind2nd 函数原型及示例 | std::bind 函数原型及示例 )

    在 STL 中 预定义了很多 函数对象 , 如果要 对 函数对象 的 参数 / 返回值 进行 计算 或 设置 , 可以 使用 \\\" 函数适配器 \\\" 实现上述需求 ; \\\" 函数适配器 \\\" 可以 将 已存在的 函数对象 转化为 另一种符合要求的 函数对象 ; \\\" 函数适配器 \\\" 定义在 functional 头文件 中 ; \\\" 函数适配器

    2024年02月02日
    浏览(63)
  • 【c++】:反向迭代器适配器:每天学一点点优秀的思想

        文章目录 前言 一、list的反向迭代器         vector的反向迭代器 总结   反向迭代器的适配只用于双向迭代器,对于单链表实现的单向迭代器是不能通过适配构造一个反向迭代器的,为什么要说反向迭代器适配器呢?因为我们只需要实现一个反向迭代器模板就可以用所有

    2023年04月09日
    浏览(43)
  • 【C++STL标准库】算法,仿函数与空间适配器

    长得像函数,但是不是函数 实际上就是在类或结构体中重载了()运算符 结构体仿函数: 类仿函数: 使用: 运行截图: 基本概念这里就不浪费时间介绍了,代码中有介绍到,这里给出空间适配器的基本使用方式: 基本概念这里就不浪费时间介绍了,代码中有介绍到: 运

    2024年02月15日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包