C++ 教程

C++ 教程 C++ 简介 C++ 下载安装和环境配置 C++ 快速入门 C++ 语法 C++ 输出 C++ 注释 C++ 变量 C++ 用户输入 C++ 数据类型 C++ 运算符 C++ 字符串 C++ 数学运算 C++ 布尔值 C++ 条件语句 C++ Switch 语句 C++ While 循环 C++ For 循环 C++ Break/Continue 语句 C++ 数组 C++ 结构体 C++ 枚举 C++ 引用 C++ 指针 C++ 内存管理

C++ 函数

C++ 函数 C++ 函数参数 C++ 函数重载 C++ 作用域 C++ 递归 C++ Lambda 表达式

C++ 面向对象

C++ OOP C++ 类和对象 C++ 类方法 C++ 构造函数 C++ 访问修饰符 C++ 封装 C++友元函数 C++ 继承 C++ 多态

C++ 错误

C++ 错误 C++ 调试 C++ 异常 C++ 输入验证

C++ 数据结构

C++ 数据结构和 STL C++ 向量 C++ 列表 C++ 栈 C++ 队列 C++ 双端队列 C++ 集合 C++ 映射 C++ 迭代器 C++ 算法

C++命名空间

C++ 命名空间

C++ 项目

C++ 项目

C++ 如何使用

C++ 两个数相加 C++ 随机数

C++ 关键字与函数参考

C++ 参考 C++ 关键字 C++ <iostream> C++ <fstream> C++ <cmath> C++ <string> C++ <cstring> C++ <ctime> C++ <vector> C++ <algorithm>

C++ 高级教程

C++ 动态内存 C++ 预处理器 C++ 信号处理 C++ 多线程 C++ Web 编程 C++ 正则表达式

C++ 实例

C++ 实例 C++ 练习 C++ 测验 C++ 编译器

C++ 标准库参考

C++ 标准库 - 简介 C++ 标准库 - <fstream> C++ 标准库 - <iomanip> C++ 标准库 - <ios> C++ 标准库 - <iosfwd> C++ 标准库 - <iostream> C++ 标准库 - <istream> C++ 标准库 - <ostream> C++ 标准库 - <sstream> C++ 标准库 - <streambuf> C++ 标准库 - <atomic> C++ 标准库 - <complex> C++ 标准库 - <exception> C++ 标准库 - <functional> C++ 标准库 - <limits> C++ 标准库 - <locale> C++ 标准库 - <memory> C++ 标准库 - <new> C++ 标准库 - <numeric> C++ 标准库 - <regex> C++ 标准库 - <stdexcept> C++ 标准库 - <string> C++ 标准库 - <thread> C++ 标准库 - <tuple> C++ 标准库 - <typeinfo> C++ 标准库 - <utility> C++ 标准库 - <valarray>

C++ 模板库参考

C++ STL 库 - <array> C++ STL 库 - <bitset> C++ STL 库 - <deque> C++ STL 库 - <forward_list> C++ STL 库 - <list> C++ STL 库 - <map> C++ STL 库 - <queue> C++ STL 库 - <set> C++ STL 库 - <stack> C++ STL 库 - <unordered_map> C++ STL 库 - <unordered_set> C++ STL 库 - <vector> C++ STL 库 - <algorithm> C++ STL 库 - <iterator>



C++ 迭代器


C++ 迭代器

迭代器用于访问和遍历数据结构(向量、集合 等)的元素,通过"指向"它们来实现。

之所以称之为"迭代器",是因为"迭代"是循环的技术术语。

要遍历一个向量,请看以下示例:

示例

// 创建一个名为 cars 的向量,用于存储字符串。
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

// 创建一个名为 it 的向量迭代器
vector<string>::iterator it;

// 使用迭代器遍历向量
for (it = cars.begin(); it != cars.end(); ++it) {
  cout << *it << "";
}
亲自试一试 »

示例详解

  1. 首先,我们创建一个字符串向量来存储不同汽车制造商的名称。
  2. 然后,我们创建一个名为 it 的"向量迭代器",我们将使用它来遍历该向量。
  3. 接下来,我们使用 for 循环,通过迭代器遍历向量。迭代器(it)指向向量(cars.begin())中的第一个元素,只要 it 不等于 cars.end(),循环就会继续。
  4. 递增运算符 (++it) 将迭代器移动到向量中的下一个元素。
  5. 解引用运算符 (*it) 访问迭代器指向的元素。

注意:迭代器的类型必须与其要迭代的数据结构类型匹配(在本例中为string)


什么是 begin() 和 end()?

begin() 和 end() 是 属于数据结构 的函数,例如 向量 和 列表。它们 不属于迭代器 本身。相反,它们与迭代器一起使用,用于访问和遍历这些数据结构的元素。

  • begin() 返回一个指向数据结构第一个元素的迭代器。
  • end() 返回一个指向最后一个元素之后位置的迭代器。

为了理解它们的工作原理,我们继续以向量为例:

vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

vector<string>::iterator it;

开始示例

begin() 指向向量中的第一个元素(索引 0,即"Volvo"):

示例

// Point to the first element in the vector
it = cars.begin();
亲自试一试 »

要指向第二个元素(BMW),您可以写cars.begin() + 1:

示例

// Point to the second element
it = cars.begin() + 1;
亲自试一试 »

当然,这也意味着您可以使用 cars.begin() + 2 指向第三个元素:

示例

// Point to the third element
it = cars.begin() + 2;
亲自试一试 »

示例结束

end() 指向向量中最后一个元素之后的一个位置(这意味着它并不指向实际的元素,而是表示这是向量的末尾)。

所以,要使用 end() 指向 cars 向量中的最后一个元素(Mazda),可以使用 cars.end() - 1:

示例

// Point to the last element
it = cars.end() - 1;
亲自试一试 »

为什么我们说"指向"?

迭代器类似于"指针",它们指向数据结构中的元素,而不是从中返回值。它们指向一个特定的位置,提供了一种在需要时访问和修改值的方法,而无需复制该值。例如:

示例

// 指向向量中的第一个元素
it = cars.begin();

// Modify the value of the first element
*it = "Tesla";

// Volvo is now Tesla
亲自试一试 »

auto 关键字

在 C++ 11 及更高版本中,您可以使用 auto 关键字,而无需显式声明和指定迭代器的类型。

auto关键字允许编译器自动确定正确的数据类型,从而简化代码并提高可读性:

而不是这样:

vector<string>::iterator it = cars.begin();

您可以直接这样写:

auto it = cars.begin();
亲自试一试 »

在上面的例子中,编译器根据 cars.begin() 的返回类型来确定 it 的类型。即 vector<string>::iterator。

auto关键字在for循环中也有效:

for (auto it = cars.begin(); it != cars.end(); ++it) {
  cout << *it << " ";
}
亲自试一试 »


For-Each 循环 vs. 迭代器

您可以使用 for-each 循环来遍历数据结构中的元素,如下所示:

示例

// 创建一个名为 cars 的向量,用于存储字符串。
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

// Print vector elements
for (string car : cars) {
  cout << car << " ";
}
亲自试一试 »

当只是读取元素而不需要修改它们时,foreach 循环比迭代器更简洁明了。

但是,当需要在迭代过程中添加、修改或删除元素,反向迭代,或跳过某些元素时,则应该使用迭代器。

示例

// 创建一个名为 cars 的向量,用于存储字符串。
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

// 遍历向量元素
for (auto it = cars.begin(); it != cars.end(); ) {
  if (*it == "BMW") {
    it = cars.erase(it); // Remove the BMW element
  } else {
    ++it;
  }
}

// Print vector elements
for (const string& car : cars) {
  cout << car << " ";
}
亲自试一试 »

反向迭代

要反向迭代,可以使用 rbegin() 和 rend() 代替 begin() 和 end():

示例

// 按相反顺序迭代
for (auto it = cars.rbegin(); it != cars.rend(); ++it) {
  cout << *it << " ";
}
亲自试一试 »

遍历其他数据结构

迭代器非常适合代码重用,因为您可以使用相同的语法遍历向量、列表、双端队列、集合和映射:

列表示例

// 创建一个名为 cars 的列表,用于存储字符串。
list<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

// 使用迭代器遍历列表
for (auto it = cars.begin(); it != cars.end(); ++it) {
  cout << *it << "";
}
亲自试一试 »

双端队列示例

// 创建一个名为 cars 的双端队列,用于存储字符串。
deque<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

// 使用迭代器遍历双端队列
for (auto it = cars.begin(); it != cars.end(); ++it) {
  cout << *it << "";
}
亲自试一试 »

举例说明

// 创建一个名为 cars 的集合,用于存储字符串。
set<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

// 使用迭代器遍历集合
for (auto it = cars.begin(); it != cars.end(); ++it) {
  cout << *it << " ";
}
亲自试一试 »

映射示例

// 创建一个用于存储字符串和整数的映射表。
map<string, int> people = { {"John", 32}, {"Adele", 45}, {"Bo", 29} };

// 使用迭代器遍历映射
for (auto it = people.begin(); it != people.end(); ++it) {
  cout << it->first << " is: " << it->second << "";
}
亲自试一试 »

迭代器支持

以上示例展示了如何遍历支持迭代器的不同数据结构(vector、list、deque、map 和 set 支持迭代器,而 stacks 和 queues 不支持迭代器)。


算法

迭代器的另一个重要特性是它们可以与不同的算法函数一起使用,例如 sort() 和 find()(位于 库中),用于对数据结构中的元素进行排序和查找。

例如,sort() 函数接受迭代器(通常由 begin() 和 end() 返回)作为参数,以从头到尾对数据结构中的元素进行排序。

在这个例子中,由于元素是字符串,所以它们按字母顺序排序:

示例

#include <iostream>
#include <vector>
#include <algorithm>  // Include the <algorithm> library
using namespace std;

int main() {
  // 创建一个名为 cars 的向量,用于存储字符串。
  vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};

  // 按字母顺序排列汽车
  sort(cars.begin(), cars.end());

  // 按字母顺序打印汽车
  for (string car : cars) {
    cout << car << " ";
  }

  return 0;
}
亲自试一试 »

在这个例子中,由于元素都是整数,所以它们是按数值排序的。

示例

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

int main() {
  // 创建一个名为 numbers 的向量,用于存储整数。
  vector<int> numbers = {1, 7, 3, 5, 9, 2};

  // 按数字排序
  sort(numbers.begin(), numbers.end());

  for (int num : numbers) {
    cout << num << " ";
  }

  return 0;
}
亲自试一试 »

要反转顺序,您可以使用 rbegin() 和 rend() 代替 begin() 和 end():

示例

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

int main() {
  // 创建一个名为 numbers 的向量,用于存储整数。
  vector<int> numbers = {1, 7, 3, 5, 9, 2};

  // 按数值大小逆序排列数字
  sort(numbers.rbegin(), numbers.rend());

  for (int num : numbers) {
    cout << num << " ";
  }

  return 0;
}
亲自试一试 »