C++标准模板(STL)- 迭代器库-迭代器适配器 - 逆序遍历的迭代器适配器

news2024/10/7 4:24:02

迭代器库-迭代器适配器

迭代器库提供了五种迭代器的定义,同时还提供了迭代器特征、适配器及相关的工具函数。

迭代器分类


迭代器共有五 (C++17 前)六 (C++17 起)种:遗留输入迭代器 (LegacyInputIterator) 、遗留输出迭代器 (LegacyOutputIterator) 、遗留向前迭代器 (LegacyForwardIterator) 、遗留双向迭代器 (LegacyBidirectionalIterator) 、遗留随机访问迭代器 (LegacyRandomAccessIterator) ,及 遗留连续迭代器 (LegacyContiguousIterator) (C++17 起)。

迭代器的分类的依据并不是迭代器的类型,而是迭代器所支持的操作。换句话说,某个类型只要支持相应的操作,就可以作为迭代器使用。例如,完整对象类型指针支持所有遗留随机访问迭代器 (LegacyRandomAccessIterator) 要求的操作,于是任何需要遗留随机访问迭代器 (LegacyRandomAccessIterator) 的地方都可以使用指针。

迭代器的所有类别(除了遗留输出迭代器 (LegacyOutputIterator) 和遗留连续迭代器 (LegacyContiguousIterator) )能组织到层级中,其中更强力的迭代器类别(如遗留随机访问迭代器 (LegacyRandomAccessIterator) )支持较不强力的类别(例如遗留输入迭代器 (LegacyInputIterator) )的所有操作。若迭代器落入这些类别之一且亦满足遗留输出迭代器 (LegacyOutputIterator) 的要求,则称之为可变 迭代器并且支持输入还有输出。称非可变迭代器为常迭代器。

逆序遍历的迭代器适配器

std::reverse_iterator
template< class Iter >

class reverse_iterator : public std::iterator<
                           typename std::iterator_traits<Iter>::iterator_category,
                           typename std::iterator_traits<Iter>::value_type,
                           typename std::iterator_traits<Iter>::difference_type,
                           typename std::iterator_traits<Iter>::pointer,

                           typename std::iterator_traits<Iter>::reference >
(C++17 前)

template< class Iter >
class reverse_iterator;

(C++17 起)

std::reverse_iterator 是一个反转给定迭代器方向的迭代器适配器。换言之,提供双向迭代器时, std::reverse_iterator 产生一个新的迭代器,它从底层的双向迭代器所定义的序列的末尾移动到开端。

对于从迭代器 i 构造的 r 逆向迭代器,关系 &*r == &*(i-1) 始终为 true (只要 r 可解引用);从而构造自末尾后一位置的迭代器的逆向迭代器解引用到序列的最后元素。

这是标准库容器的成员函数 rbegin()rend() 所返回的迭代器。

成员类型

成员类型定义
iterator_typeIter
iterator_concept
(C++20 起)
Iter 实现 std::random_access_iterator ,则为 std::random_access_iterator_tag 。否则为 std::bidirectional_iterator_tag
iterator_category

std::iterator_traits<Iter>::iterator_category

(C++20 前)

若 std::iterator_traits<Iter>::iterator_category 实现 std::derived_from<std::random_access_iterator_tag> ,则为 std::random_access_iterator_tag 。否则为不更改的 std::iterator_traits<Iter>::iterator_category

(C++20 起)
value_type

std::iterator_traits<Iter>::value_type

(C++20 前)

std::iter_value_t<Iter>

(C++20 起)
difference_type

std::iterator_traits<Iter>::difference_type

(C++20 前)

std::iter_difference_t<Iter>

(C++20 起)
pointerstd::iterator_traits<Iter>::pointer
reference

std::iterator_traits<Iter>::reference

(C++20 前)

std::iter_reference_t<Iter>

(C++20 起)

要求通过从 std::iterator<std::iterator_traits<Iter>::iterator_category
, std::iterator_traits<Iter>::value_type
, std::iterator_traits<Iter>::difference_type
, std::iterator_traits<Iter>::pointer
, std::iterator_traits<Iter>::reference
> 继承获得成员类型 iterator_categoryvalue_typedifference_typepointerreference

(C++17 前)

成员函数

(构造函数)

构造新的迭代器适配器
(公开成员函数)

operator=

赋值另一迭代器
(公开成员函数)

base

访问底层迭代器
(公开成员函数)

operator*operator->

访问指向的元素
(公开成员函数)

operator[]

按索引访问元素
(公开成员函数)

operator++operator++(int)operator+=operator+operator--operator--(int)operator-=operator-

推进或回退迭代器
(公开成员函数)

成员对象

成员名称定义
current (受保护成员对象)base() 迭代器的副本

非成员函数

make_reverse_iterator

(C++14)

创建拥有从实参推出的类型的 std::reverse_iterator
(函数模板)

operator==operator!=operator<operator<=operator>operator>=

比较底层迭代器
(函数模板)

operator+

令迭代器前进
(函数模板)

operator-

计算两个迭代器适配器间的距离
(函数模板)

iter_move

(C++20)

转型解引用调整后的底层迭代器的结果为其所关联的右值引用类型
(函数模板)

iter_swap

(C++20)

交换二个调整后的底层迭代器所指向的对象
(函数模板)

注意

std::reverse_iterator 不可作用于返回到成员对象引用的迭代器(是谓“隐匿迭代器”)。隐匿迭代器的一个例子是 std::filesystem::path::iterator 。

调用示例

#include <iostream>
#include <string>
#include <iterator>
#include <deque>
#include <algorithm>
#include <time.h>

struct Cell
{
    int x;
    int y;

    Cell() = default;
    Cell(int a, int b): x(a), y(b) {}

    Cell &operator +=(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator +(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator *(const Cell &cell)
    {
        x *= cell.x;
        y *= cell.y;
        return *this;
    }

    Cell &operator ++()
    {
        x += 1;
        y += 1;
        return *this;
    }

    bool operator <(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }

    bool operator ==(const Cell &cell) const
    {
        return x == cell.x && y == cell.y;
    }
};

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}

template< class BDIter >
void alg(BDIter, BDIter, std::input_iterator_tag)
{
    //遗留输入迭代器
    std::cout << "alg() called for input iterator" << std::endl;
}

template< class BDIter >
void alg(BDIter, BDIter, std::output_iterator_tag)
{
    //遗留输出迭代器
    std::cout << "alg() called for output iterator" << std::endl;
}

template< class BDIter >
void alg(BDIter, BDIter, std::forward_iterator_tag)
{
    //遗留向前迭代器
    std::cout << "alg() called for forward iterator" << std::endl;
}

template< class BDIter >
void alg(BDIter, BDIter, std::bidirectional_iterator_tag)
{
    //遗留双向迭代器
    std::cout << "alg() called for bidirectional iterator" << std::endl;
}

template <class RAIter>
void alg(RAIter, RAIter, std::random_access_iterator_tag)
{
    //遗留随机访问迭代器
    std::cout << "alg() called for random-access iterator" << std::endl;
}

template< class Iter >
void alg(Iter first, Iter last)
{
    alg(first, last,
        typename std::iterator_traits<Iter>::iterator_category());
}

int main()
{
    std::string string = "Hello, world";
    std::reverse_iterator<std::string::iterator> reverse_iterator = string.rbegin();
    string[7] = 'O'; // 以 'O' 替换 'o'
    string += 7; // 迭代器现在指向 'O'
    alg(reverse_iterator, reverse_iterator);
    std::cout << "string:   " << string << std::endl;
    std::string reverse_string(reverse_iterator, string.rend());
    std::cout << "reverse_string:   " << reverse_string << std::endl;
    std::cout << std::endl;

    std::mt19937 g{std::random_device{}()};

    srand((unsigned)time(NULL));;

    std::cout << std::boolalpha;

    auto generate = []()
    {
        int n = std::rand() % 10 + 100;
        Cell cell{n, n};
        return cell;
    };

    {
        std::deque<Cell> deque1(6);
        std::generate(deque1.begin(), deque1.end(), generate);
        std::cout << "deque1 :  ";
        std::copy(deque1.begin(), deque1.end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;

        std::cout << "deque1 reverse :  ";
        for (std::deque<Cell>::reverse_iterator rit = deque1.rbegin(); rit != deque1.rend(); rit++)
        {
            std::cout << *rit << " ";
        }
        std::cout << std::endl;
        alg(deque1.rbegin(), deque1.rend());
    }

    return 0;
}

输出

alg() called for random-access iterator
string:   Hello, Oorld
reverse_string:   dlroO ,olleH

deque1 :  {109,109} {106,106} {101,101} {107,107} {103,103} {102,102}
deque1 reverse :  {102,102} {103,103} {107,107} {101,101} {106,106} {109,109}
alg() called for random-access iterator

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1788721.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年城市建设与环境管理国际会议(ICUCEM 2024)

2024 International Conference on Urban Construction and Environmental Management 【1】大会信息 大会地点&#xff1a;中国成都 投稿邮箱&#xff1a;icucemsub-paper.com 【2】会议简介 2024年城市建设与环境管理国际会议是一个专注于探讨城市建设与环境管理前沿议题…

#02 安装指南:如何配置Stable Diffusion环境

文章目录 前言前置条件第1步&#xff1a;安装Python和PIP第2步&#xff1a;创建虚拟环境第3步&#xff1a;安装PyTorch和CUDA第4步&#xff1a;安装Stable Diffusion相关库第5步&#xff1a;测试环境结论 前言 在之前的文章中&#xff0c;我们介绍了Stable Diffusion基础入门和…

【ArcGIS微课1000例】0114:基于DEM地形数据整体抬升或下降高程

相关阅读:【GlobalMapper精品教程】083:基于DEM整体抬升或下降地形高程的两种方式 文章目录 一、任务分析二、栅格计算器简介三、地形整体修改四、注意事项一、任务分析 打开软件,加载配套实验数据中的0112.rar中的dem数据,如下所示,dem的高程范围为256.75~342.37米,现在…

QT之动态加载树节点(QTreeWidget)

之前写过一篇动态加载ComboBox&#xff0c;可参见下面这篇文章 QT之动态加载下拉框&#xff08;QComboBox&#xff09; 同理QTreeWidget也可以实现动态加载&#xff0c;在一些异步加载数据&#xff0c;并且数据加载比较耗时&#xff0c;非常实用。 效果 原理分析 要实现此类效…

618精选网络安全书单:打造数字世界的钢铁长城!

文章目录 《内网渗透实战攻略》《Kali Linux高级渗透测试&#xff08;原书第4版&#xff09;》《CTF那些事儿》《权限提升技术&#xff1a;攻防实战与技巧》《数字政府网络安全合规性建设指南&#xff1a;密码应用与数据安全》《红蓝攻防&#xff1a;构建实战化网络安全防御体系…

ECharts 图形化看板 模板(简单实用)

目录 一、官网 二、模板 ①定义请求​编辑 ② 将请求统一管理&#xff0c;别的页面引用多个请求时更便于导入。​编辑 ③最终模板 三、执行效果 四、后端代码 4.1 controller 4.2 xml 4.3 测试接口 一、官网 获取 ECharts - 入门篇 - 使用手册 - Apache ECharts 二、…

医疗器械网络安全风险管理的基本步骤

医疗器械网络安全风险管理是一个复杂的过程&#xff0c;涉及到多个环节和步骤。以下是一些基本的步骤和关键点&#xff1a; 风险识别&#xff1a;首先需要对医疗器械的软件、网络连接和通信协议等进行漏洞分析&#xff0c;识别潜在的安全漏洞和弱点。这可能涉及对设备的渗透测…

佛教祭拜小程序-寺庙小程序-纪念馆小程序

大家好&#xff0c;我是程序员小孟。 现在有很多的产品或者工具都开始信息话了&#xff0c;寺庙或者佛教也需要小程序吗&#xff1f; 当然了&#xff01; 前面我们还开发了很多寺庙相关的小程序&#xff0c;都有相关的介绍&#xff1a; 1,优质的寺庙小程序-H5寺庙网页 今天…

jmeter常用的断言

包括&#xff08;Contains&#xff09;&#xff1a;响应内容包括需要匹配的内容即代表响应成功&#xff0c;支持正则表达式 匹配&#xff08;Matches&#xff09;&#xff1a;响应内容要完全匹配需要匹配的内容即代表响应成功&#xff0c;大小写不敏感&#xff0c;支持正则表达…

2. redis配置文件解析

redis配置文件解析 一、redis配置文件1、监听地址2、监听端口3、redis接收请求的队列长度3.1 修改系统参数/内核参数 4、客户端空闲的超时时间5、指定redis的pid文件6、定义错误日志7、定义数据库的数量8、定义持久化存储9、设置redis密码10、redis并发连接11、最大内存策略 二…

python的一种集成开发工具:PyCharm开发工具

一. 简介 本文简单了解两种 python语言所使用的 集成开发环境&#xff1a; PyCharm、vscode。 python语言学习中&#xff0c;可以任意选中这两个集成开发环境的一种就可以。本文先来简单学习 PyCharm开发工具安装与使用。 二. python的一种集成开发工具&#xff1a;PyChar…

Warning:成交前,永远相信意外即将发生

作为一名首次次创业者&#xff0c;随着创业进入深层次阶段&#xff0c;越来越感觉到&#xff1a;创业是一条不归路&#xff0c;因为路上不止有惊喜&#xff0c;还有风尘。创业之前我认为世界是“天圆地方”的&#xff0c; 创业后你猜我怎么看这个世界的&#xff1f; 创业前我一…

ARM32开发——串口库封装(初级)

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 开发流程分组创建 接口定义完整代码 开发流程 在文件系统中&#xff0c;创建库目录Library在keil工程中&#xff0c;创建分组管理…

健身日记之倒立俯卧撑学习——起始日2024.6.4

文章目录 前言 自我介绍 昔日计划 新目标计划 瓶颈突破尝试 参考视频及文章 前言 有轻微健身基础&#xff0c;正式接触街健五大神技&#xff0c;立志在两年内解锁全部&#xff0c;将有机会的进行日常训练和目标肌群锻炼&#xff0c;这里向大家展示我的计划和安排&#xf…

【C++练级之路】【Lv.24】异常

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、异常的概念及定义1.1 异常的概念1.2 异常的定义 二、异常的使用2.1 异常的栈展开匹配2.2 异常的重新…

Django使用正则表达式

本书1-7章样章及配套资源下载链接: https://pan.baidu.com/s/1OGmhHxEMf2ZdozkUnDkAkA?pwdnanc 源码、PPT课件、教学视频等&#xff0c;可以从前言给出的下载信息下载&#xff0c;大家可以评估一下。 在Django框架的新版本&#xff08;v2.0 &#xff09;中&#xff0c;URLc…

电脑开机之后要很久才能进入系统?进入WinPE也是卡顿半天?

前言 小白最近接到了一张很奇怪的电脑维修单&#xff0c;客户说他的工作室电脑开机特别慢&#xff0c;开机之后特别卡顿&#xff0c;在使用的时候也会一卡一卡的。 这事情开始看很简单&#xff1a;估计就是电脑还是机械硬盘&#xff0c;所以开机很慢又卡顿。所以应该是把机械…

一键开启:盲盒小程序里的梦幻奇遇

在繁忙的都市生活中&#xff0c;每个人心中都藏着一个关于奇遇的梦想。如今&#xff0c;我们为您精心打造了一款盲盒小程序——“梦幻奇遇”&#xff0c;只需一键开启&#xff0c;就能带您走进一个充满无限惊喜和梦幻色彩的奇幻世界。 一、神秘盲盒&#xff0c;惊喜连连 “梦幻…

SolidWorks价格与其它CAD软件相比:为什么选择SolidWorks更划算

在CAD软件的浩瀚星海中&#xff0c;SolidWorks如同一颗璀璨的明星&#xff0c;以其卓越的性能、广泛的适用性和合理的定价策略&#xff0c;赢得了全球众多工程师和设计师的青睐。亿达四方&#xff0c;作为官方授权的SolidWorks代理商&#xff0c;今天将带您深入价格与功能的比较…

21、matlab生成脉冲序列:pulstran()函数

1、pulstran()函数 1&#xff09;语法 语法1&#xff1a;y pulstran(t,d,func,fs) 基于连续函数的采样产生脉冲序列。 语法2&#xff1a;y pulstran(t,d,p) 生成一个脉冲序列&#xff0c;该脉冲序列是向量p中原型脉冲的多个延迟插值的总和。 语法3&#xff1a;y pulstran…