C++教程之迭代器Iterator

2023-05-16

前言

之前的两篇文章我们主要了解了vector和string的相关知识,从中我们知道可以通过下标来访问vector的元素或者string的字符,但是除了这种方式还有一种更为通用的方式获取元素,那就是迭代器,这篇文章就会简单介绍迭代器的相关内容。

迭代器简介

在我们使用容器去存储元素的时候有时候会需要获取存储的元素,而迭代器就是用于从容器中获取元素的,基本上所有容器的库都支持迭代器,但是只有其中一小部分支持下标获取元素的。虽然string不是容器但是其支持很多容器的操作,其中就包括下标和迭代器。

与指针类似,迭代器提供了一种间接获取对象的方式,对于迭代器而言,这个对象就是容器中的元素或者string中的字符,我们可以通过迭代器获取一个元素,与此同时也可以将指向的对象从一个对象移到下一个对象。迭代器还和指针一样有有效和无效之分,所有代表容器中元素或最后一个元素的下一个位置都是有效的,其他所有的迭代器都是无效的。

迭代器的使用

不像指针,我们不使用地址操作符去获取一个迭代器,每一个支持迭代器的类型都有函数可以返回迭代器,这些类型都有名为begin和end的函数,begin返回的是代表第一个元素的迭代器,end的返回的迭代器是容器或者字符串的最后一个元素的下一个位置,这个迭代器代表着最后一个元素的下一个位置,是一个不存在的元素。如果容器为空,则begin和end返回的是同一个迭代器。

auto b = v.begin(), e = v.end()

迭代器的操作

迭代器只支持下表列出来的操作,我们可以通过==或!=比较两个有效的迭代器,如果迭代器代表着同一个元素或者都是最后一个元素的下一个位置则相等,否则它们不等。
|操作|解释|
|*iter|返回迭代器代表的指针指向的值|
|iter->mem|等价于(*iter).mem|
|++iter|指向容器中的下一个元素|
|–iter|指向容器中的前一个元素|
|iter1 == iter2|判断两个迭代器是否相等|
|iter1 != iter2|判断两个迭代器是否不等|

对于指针,我们可以使用解引用符获取一个迭代器的元素,和指针相同,我们只能通过解引用符获取一个有效的迭代器的元素,如果解引用一个最后一个元素之后的迭代器结果是未知的。

# include<iostream>
# include<string>
using namespace std;


int main() {
  string s("some string");
  if (s.begin() != s.end()) {
    auto it = s.begin();
    *it = toupper(*it);
  }
  cout<<s<<endl;
  }

上述的例子就是通过迭代器获取字符串s的首个字符并将其大写。

迭代器从一个元素移动到另一个元素

迭代器私用自增操作符从一个元素移动到该元素的下一个元素,自增一个迭代器与自增一个整型十分类似,对于整型而言,自增的是其本身的值,对于迭代器而言,其影响是往前进一个位置。

由于end返回的不是一个元素,所以其不能自增或者解引用

使用自增操作我们可以重写之前的程序:

# include<iostream>
# include<string>
using namespace std;


int main() {
  string s("some string");
  for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it) {
    *it = toupper(*it);
  }
  cout<<s<<endl;
  }

如上例所示,我们通过迭代器可以实现循环遍历。

迭代器的类型

正如我们并不准确知道vector的准确类型或者string的size,同样的,我们也不知道同时也不需要知道迭代器的准确类型,但是根据迭代器的读写权限定义了以下几种迭代器的类型:

 vector<int>::iterator it; //it可以读也可以写vector<int>的元素
  string::iterator it2; //it2可以读写字符串里的字符
  vector<int>::const_iterator it3; //it3可以读但是不可以写元素
  string::const_iterator it4; //it4可以读但是不可以写字符串里面的字符

const_iterator表现就像是常量指针,可以读取元素但是不能写元素

begin和end操作

begin和end返回的结果取决于它们操作的对象是不是常量,如果操作对象是常量,那么begin和end返回的就是const_iterator,如果对象不是常量,那么返回的就是iterator。

# include<iostream>
# include<string>
# include<vector>
using namespace std;


int main() {
vector<int> v;
const vector<int> cv;
auto it1 = v.begin(); //it返回的是vector<int>::iterator
auto it2 = v.begin(); //it返回的是vector<int>::const_iterator
}

这种默认的返回策略有时候并不满足需求,在一些情况下一些非常量的vector我们只想读取元素,避免元素被更改,在C++11中提供了以下新的方法cbegin和cend,无论vetor是不是常量都返回const_iterator。

auto it3 = v.cbegin();

迭代器的数学运算

处理之前提到自增和自减外,迭代器还支持以下数学运算,虽然迭代器是没有下标的概念的,但是一下运算都可以理解为是对于下标的操作,如加减就是自增和自减的普通形式,就是向前移动或者向后移动,大小比较就是前后位置的比较。

操作解释
iter + n同一个容器向前移动n
iter - n同一个容器向后移动
iter1 += n将移动结果赋值给iter1
iter1 -= n将移动结果赋值给iter1
>, >=, <, <=相对位置的比较

这么说起来可能又带你抽象,下面用一个二分法来说明:

# include<iostream>
# include<string>
# include<vector>
using namespace std;


int main() {
  vector<int> v = {1, 2, 3, 4, 5};
  auto beg = v.begin(), end = v.end();
  auto mid = v.begin() + (end - beg) / 2;
  int target = 2;
  while (mid != end && *mid != target)
  {
    if (target < *mid) {
      end = mid;
    } else{
      beg = mid;
    }
    mid = beg + (end - beg) / 2;
  }
  cout<<to_string(*mid)<<endl;
  }

以上例子会打印2,也就是元素2的位置。

最后

这篇文章主要介绍了C++中的迭代器,更多文章可以关注公众号QStack。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++教程之迭代器Iterator 的相关文章

  • 如何在 Spark Java 中遍历/迭代数据集?

    我正在尝试遍历数据集来进行一些字符串相似度计算 例如 Jaro winkler 或余弦相似度 我将数据集转换为行列表 然后使用 for 语句进行遍历 这不是有效的 Spark 方法 所以我期待 Spark 中有更好的方法 public cl
  • 在 Rust 中将递归函数转换为迭代器的技术?

    我正在努力将一个简单的递归函数变成一个简单的迭代器 问题在于递归函数在其局部变量和调用堆栈中维护状态 将其转换为 Rust 迭代器意味着基本上将所有函数状态外部化为某些自定义迭代器结构上的可变属性 这是一个相当混乱的尝试 在 javascr
  • Julia 自定义类型分配

    我尝试从 Julia 中的自定义类型分配多个元素 但是我不知道该怎么做 或者换句话说 我想重载赋值运算符以返回该类型中包含的所有元素的元组 这是所需的行为 type foo a b end a b foo 1 2 a gt 1 这是错误消息
  • C++ 迭代模板 Map

    当我有一个包含模板映射和一个模板类const iterator声明如下代码typedef 如何迭代类外部映射的元素 例如 main 中以将它们打印在输出上 template
  • 迭代器的无限产量

    我正在尝试学习一些红宝石 想象一下 我正在循环并执行一个长时间运行的过程 在这个过程中 我希望获得一个旋转器 只要需要就可以 所以我可以这样做 a aNow 0 skip setup a big loop print a aNow aNow
  • Nim 中的迭代器生成函数:在分配迭代器时起作用,在直接调用它时卡住

    我尝试创建一个创建迭代器的过程 如下所示 proc makeCDFrom start int iterator int result iterator int var i int start while i gt 0 echo i i yi
  • 流Vs。 Map 的 EntrySet 中的迭代器 - Java 8

    据我了解 以下代码应该打印true 因为两者Stream and Iterator指向第一个元素 但是 当我运行以下代码时 它正在打印false final HashMap
  • 为什么迭代器使用“!=”而不是“<”?

    我习惯这样写循环 for std size t index 0 index lt foo size index Do stuff with foo index 但是当我在其他人的代码中看到迭代器循环时 它们看起来像这样 for Foo It
  • 向量集合上的 C++ iterator_adapter [重复]

    这个问题在这里已经有答案了 可能的重复 展平迭代器 https stackoverflow com questions 3623082 flattening iterator 我有一个某种类型的向量 比如 int 我想迭代一下 在向量中的元
  • 使用推断的 (?) 类型克隆 std::iter::Map

    我在以紧凑的方式克隆地图时遇到问题 extern crate itertools num use itertools num linspace fn main 440Hz as wave frequency middle A let fre
  • 使用 contains 或循环列表之间有什么大的区别吗?

    性能方面 使用之间真的有很大区别吗 ArrayList contains o 与 foreach iterator LinkedList contains o 与 foreach iterator 当然 对于 foreach iterato
  • 链表迭代器实现 C++

    我已经在 C 中创建了一个链接列表 并想为其实现一个迭代器 以便我可以执行范围循环 for const int i list where Linked List
  • 从tensorflow 2.0 beta中的tf.data.Dataset检索下一个元素

    在tensorflow 2 0 beta之前 要从tf data Dataset中检索第一个元素 我们可以使用迭代器 如下所示 usr bin python import tensorflow as tf train dataset tf
  • const_iterator 和 iterator 有什么区别? [复制]

    这个问题在这里已经有答案了 这两者在 STL 内部的实现方面有什么区别 性能方面有什么区别 我想当我们以 只读方式 遍历向量时 我们更喜欢const iterator right 谢谢 没有性能差异 A const iterator是一个指
  • 异步迭代器 Task>

    我正在尝试实现一个返回迭代器的异步函数 这个想法如下 private async Task
  • iteritems 的优点是什么?

    我使用的是 Python 2 7 5 Mac OS X 10 9 3 具有 8GB 内存和 1 7GHz Core i5 我测试了如下的时间消耗 d i i 2 for i in xrange 10 7 3 WARNING it takes
  • java迭代器内部是如何工作的? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个员工列表 List
  • VB.NET vNext 中的迭代器以及 C# 中迭代​​器的限制

    我刚刚在上看到异步CTP网站 http msdn microsoft com en us vstudio async aspxVB NET 的下一个版本将有迭代器 我猜它们包含了迭代器 因为重写过程与新的迭代器所使用的过程类似 async
  • C++ std::vector 搜索值

    我正在尝试优化std vector 搜索 基于索引的迭代向量并返回与 搜索 条件匹配的元素 struct myObj int id char value std vector
  • Java 中的故障安全迭代器和故障快速迭代器是什么

    Java 中有两种类型的迭代器 故障安全迭代器和故障快速迭代器 这是什么意思 它们之间有什么区别 他们之间有什么区别 故障安全 在工程方面 https en wikipedia org wiki Fail safe 表示某事物发生故障但不会

随机推荐

  • c++读取yolov5模型进行目标检测(读取摄像头实时监测)

    文章介绍 本文是篇基于yolov5模型的一个工程 xff0c 主要是利用c 43 43 将yolov5模型进行调用并测试 xff0c 从而实现目标检测任务 任务过程中主要重点有两个 xff0c 第一 版本问题 xff0c 第二配置问题 一
  • ROS初学(二):ROS的三种基本通信机制(来自赵虚左老师)

    一 综述 ROS引入通信机制 xff0c 是为了实现ROS节点 xff08 进程 xff09 之间的通信 利用ROS进程的分布式框架 xff0c 可以使得每个进程独立的工作 xff0c 甚至分布于不同的主机工作 机器人上的各种传感器 xff
  • webpack 5.5.1 compiled with 1 error in 63 ms

    新建项目空白目录 xff0c 并运行 npm init y 命令 xff0c 初始化包管理配置文件 package json 新建 src 源代码目录 新建 src gt index html 首页和 src gt index js 脚本文
  • TypeError: Class constructor ServeCommand cannot be invoked without ‘new‘

    安装webpack插件 webpack dev server配置时将package json里面webpack改为webpack serve后 xff0c 运行npm run 脚本名 时出现 TypeError Class construc
  • Field ‘browser‘ doesn‘t contain a valid alias configuration

    意思是字段 39 browser 39 不包含有效的别名配置 意思就是说你打包的css路径不对 这个是我的代码 这里js里面导入的css路径不对 xff0c css文件夹不是和index js平级 xff0c 应该是上级所以正确的代码应该是
  • Failed to load resource: the server responded with a status of 404 (Not Found)

    问题场景 xff1a 编写路由模块 解决方法 xff1a 1 先检测路径是否有写错 2 将vscode中开的插件vetur关闭 3 上面方法不管用时 xff0c 将浏览器插件关闭 xff0c 例如油猴 有什么错误望大佬指出 xff01 xf
  • Vue3.js【未完成】

    Vue3 js 如何关闭烦人的vscode的提示框 https blog csdn net liuyuemozhu article details 101056556 ES6模块化与异步编程高级用法 ES6模块化 1 回顾 xff1a no
  • npm ERR! code ERESOLVEnpm ERR! ERESOLVE unable to resolve dependency tree

    npm下载报错 xff0c 这个是因为npm版本问题 xff0c 例如我下载element ui运行npm i element ui S 因为版本问题我就无法下载 xff0c 解决办法就是在末尾加上 legacy peer deps 即np
  • 前端面试题

    浏览器 输入一个URL到页面过程中发生了什么 xff08 高频 xff09 首先在浏览器中输入URL 查找缓存 xff1a 浏览器先查看浏览器缓存 系统缓存 路由缓存中是否有该地址页面 xff0c 如果有则显示页面内容 如果没有则进行下一步
  • MATALAB动态爱心代码

    第一步 xff1a 先下载MATLAB软件 xff08 该代码只适用于此软件 xff0c 要下载软件才可运行 xff09 第二步 xff1a 点击主页 新建脚本 xff08 可自己给脚本命名 xff0c 我命名的是aixin xff09 第
  • Linux相关博文中使用的头文件

    收录博文中看到的已经封装好的文件时 xff0c 方便各位查看 Log hpp 日志信息 pragma once include lt iostream gt include lt cstdio gt include lt cstdarg g
  • 构造函数和析构函数执行顺序

    析构函数运行顺序 xff1a 1 主函数结束 xff1b 2 函数调用结束 xff1b 3 用delete删除 xff08 new创建的 xff09 对象时 注释代码运行结果 输入坐标6 xff0c 3 xff0c 6 xff0c 2 xf
  • 27.【C/C++ 最全vector数组的用法 (详解)】

    vector动态数组 xff08 一 xff09 什么是vector xff1f xff08 二 xff09 vector的作用是什么 xff08 三 xff09 经典用法 1 vector函数的定义 代码展示 效果展示 2 vector的
  • 析构函数运行顺序

    全局变量 xff0c 静态局部变量 xff0c 局部变量空间的堆分配和栈分配 其中全局变量和静态局部变量时从 静态存储区中划分的空间 xff0c 二者的区别在于作用域的不同 xff0c 全局变量作用域大于静态局部变量 xff08 只用于声明
  • 03_临界段的保护

    一 临界段的概念 所谓的临界段就是在执行时不能被中断的代码段 在FreeRTOS中 xff0c 临界段最常出现的地方就是对全局变量的操作 那么什么情况下临界段会被打断 xff1f 一个是系统调度 xff0c 还有一个是外部中断 在FreeR
  • Qt自定义窗口继承基类

    设计一个窗口基类模板 xff0c 方便子类的统一风格使用 xff0c 省略重写事件函数 xff0c 代码思路
  • ROS学习笔记4:创建工作空间和功能包

    一 linux命令行使用基础 xff1a 1 cd命令 xff08 change directory xff09 xff1a xff08 1 xff09 语法 xff1a cd dirName xff08 dirName xff1a 要切换
  • 一段代码给你讲清楚【链式存储结构】

    1 基础定义 链式存储结构 xff08 linked storage structure xff09 xff0c 是逻辑存储结构的一种 xff0c 链式存储结构中每一个逻辑元素用一个内存结点存储 xff0c 每一个结点都是单独分配的 xff
  • Flask之before_request与after_request

    Flask之before request与after request 更多的用法或说明请查看文档 xff1a https dormousehole readthedocs io en latest api html flask Flask
  • C++教程之迭代器Iterator

    前言 之前的两篇文章我们主要了解了vector和string的相关知识 xff0c 从中我们知道可以通过下标来访问vector的元素或者string的字符 xff0c 但是除了这种方式还有一种更为通用的方式获取元素 xff0c 那就是迭代器