【C/C++笔记】迭代器

简介: 【C/C++笔记】迭代器

迭代器

每种容器类型都提供若干共同工作的迭代器类型。与容器类型一样,所有迭代器具有相同的接口:如果某种迭代器支持某种操作,那么支持这种操作的其他迭代器也会以相同的方式支持这种操作。例如,所有容器迭代器都支持以解引用运算从容器中读入一个元素。类似地,容器都提供自增和自减操作符来支持从一个元素到下一个元素的访问。


常用迭代器运算

*iter : 返回迭代器 iter 所指向的元素的引用

iter->mem : 对 iter 进行解引用,获取指定元素中名为 mem 的成员。等效于 (*iter).mem

++iter iter++ : 给 iter 加 1,使其指向容器里的下一个元素

–iter iter-- : 给 iter 减 1,使其指向容器里的前一个元素


iter1 == iter2

iter1 != iter2 :比较两个迭代器是否相等(或不等)。当两个迭代器指向同一个容器中的同一个元素,或者当它们都指向同一个容器的超出末端的下一位置时,两个迭代器相等

vector 和 deque 容器的迭代器提供额外的运算

C++ 定义的容器类型中,只有 vector 和 deque 容器提供下面两种重要的运算集合:迭代器算术运算(第 3.4.1 节),以及使用除了 == 和 != 之外的关系操作符来比较两个迭代器(== 和 != 这两种关系运算适用于所有容器)。

  • vector 和 deque 类型迭代器支持的操作

iter + n

iter - n :在迭代器上加(减)整数值 n,将产生指向容器中前面(后面)第 n 个元素的迭代器。新计算出来的迭代器必须指向容器中的元素或超出容器末端的下一位置


iter1 += iter2 :这里迭代器加减法的复合赋值运算:将 iter1 加上或减去 iter2 的运算结果赋给 iter1

iter1 - iter2 :两个迭代器的减法,其运算结果加上右边的迭代器即得左边的迭代器。这两个迭代器必须指向同一个容器中的元素或超出容器末端的下一位置

- 只适用于 vector 和 deque 容器
>, >=, <, <= :迭代器的关系操作符。当一个迭代器指向的元素在容器中位于另一个迭代器指向的元素之前,则前一个迭代器小于后一个迭代器。关系操作符的两个迭代器必须指向同一个容器中的元素或超出容器末端的下一位置。

关系操作符只适用于 vector 和 deque 容器,这是因为只有这种两种容器为其元素提供快速、随机的访问。它们确保可根据元素位置直接有效地访问指定的容器元素。这两种容器都支持通过元素位置实现的随机访问,因此它们的迭代器可以有效地实现算术和关系运算。


举例

  • vector
vector<int>::iterator iter = vec.begin() + vec.size()/2;

计算 vector 对象的中点位置

  • list
// copy elements from vec into ilist
list<int> ilist(vec.begin(), vec.end());
ilist.begin() + ilist.size()/2; // error: no addition on list iterators

用法示列

(a) vector::iterator it = ivec.begin();


这个用法是正确的。it 被声明为 vector 的迭代器,并且被赋值为 ivec 的开始迭代器。

(b) list::iterator it = ilist.begin()+2;


这个用法是错误的。std::list 的迭代器不支持加法运算符。如果你想要前进到 list 的第三个元素,你应该使用循环或者 std::advance 函数。

© vector::iterator it = &svec[0];


这个用法是错误的。在C++中,你不能直接使用 & 运算符来获取 vector 的第一个元素的地址,然后将其赋给迭代器。正确的方式是使用 svec.begin()。

(d) for (vector::iterator it = svec.begin(); it != 0; ++it)


这个用法是错误的。在C++中,迭代器的比较操作符是 == 和 !=,而不是 != 0。迭代器本身不与任何数值比较,它们只与其它迭代器比较。

正确的迭代器声明和循环应该像这样:

for (vector<string>::iterator it = svec.begin(); it != svec.end(); ++it) {
    // ...
}

在这个循环中,迭代器 it 从 svec 的开始迭代器开始,一直遍历到 svec.end(),即 vector 的结束迭代器。每次循环迭代器 it 都会通过 ++it 向前移动。

std::advance讲解

函数原型

template <class InputIt, class Distance>
void advance(InputIt& it, Distance n);
  • InputIt 是迭代器的类型。
  • Distance 是步数的类型,通常是一个整数。
    std::advance 接受两个参数:一个迭代器引用 it 和一个表示步数的 n。如果 n 是正数,函数将迭代器向前移动 n 步;如果 n 是负数,函数将迭代器向后移动 -n 步。
// 向后移动3步,回到开始位置
std::advance(it, -3);

std::advance 的行为取决于迭代器的类别。对于只读迭代器(如 std::list 的迭代器),std::advance 只允许正数步进。对于随机访问迭代器(如 std::vector 或 std::deque 的迭代器),std::advance 可以处理正数和负数步进。


相关文章
|
3月前
|
算法 C++
算法笔记:递归(c++实现)
算法笔记:递归(c++实现)
|
3月前
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
|
24天前
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
50 0
|
2月前
|
C++ Windows
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
在Windows上使用Visual Studio 2022进行FFmpeg和SDL2集成开发,首先安装FFmpeg至E:\msys64\usr\local\ffmpeg,然后新建C++控制台项目。在项目属性中,添加FFmpeg和SDL2的头文件及库文件目录。接着配置链接器的附加依赖项,包括多个FFmpeg及SDL2的lib文件。在代码中引入FFmpeg的`av_log`函数输出"Hello World",编译并运行,若看到"Hello World",即表示集成成功。详细步骤可参考《FFmpeg开发实战:从零基础到短视频上线》。
66 0
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
|
3月前
|
编译器 C语言 C++
C++ STL中list迭代器的实现
C++ STL中list迭代器的实现
C++ STL中list迭代器的实现
|
3月前
|
算法 数据处理 C++
C++一分钟之-迭代器与算法
【6月更文挑战第21天】C++ STL的迭代器统一了容器元素访问,分为多种类型,如输入、输出、前向、双向和随机访问。迭代器使用时需留意失效和类型匹配。STL算法如查找、排序、复制要求特定类型的迭代器,注意容器兼容性和返回值处理。适配器和算法组合增强灵活性,但过度使用可能降低代码可读性。掌握迭代器和算法能提升编程效率和代码质量。
41 3
|
3月前
|
存储 编译器 Linux
C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题
C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题
42 7
|
2月前
|
C++ 容器
【C++】string类的使用①(迭代器接口begin,end,rbegin和rend)
迭代器接口是获取容器元素指针的成员函数。`begin()`返回首元素的正向迭代器,`end()`返回末元素之后的位置。`rbegin()`和`rend()`提供反向迭代器,分别指向尾元素和首元素之前。C++11增加了const版本以供只读访问。示例代码展示了如何使用这些迭代器遍历字符串。
|
4月前
|
C语言
从C语言到C++_29(红黑树封装set和map)红黑树迭代器的实现(下)
从C语言到C++_29(红黑树封装set和map)红黑树迭代器的实现
38 3
|
3月前
|
编译器 C++
C++ 反向迭代器的设计与实现
C++ 反向迭代器的设计与实现