Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

C++ 教程

C++ 主页 C++ 简介 C++ 入门 C++ 语法 C++ 输出 C++ 注释 C++ 变量 C++ 用户输入 C++ 数据类型 C++ 运算符 C++ 字符串 C++ 数学 C++ 布尔值 C++ If...Else C++ Switch C++ While 循环 C++ For 循环 C++ Break/Continue C++ 数组 C++ 结构体 C++ 枚举 C++ 引用 C++ 指针

C++ 函数

C++ 函数 C++ 函数参数 C++ 函数重载 C++ 作用域 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++ <iostream> C++ <fstream> C++ <cmath> C++ <string> C++ <cstring> C++ <ctime> C++ <vector> C++ <algorithm>

C++ 例子

C++ 例子 C++ 现实例子 C++ 编译器 C++ 练习 C++ 问答 C++ 证书


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 << "\n";
}
自己尝试 »

示例解释

  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 示例

begin() 指向向量中的第一个元素(索引 0,即“Volvo”)。

示例

// 指向向量中的第一个元素
it = cars.begin();
自己尝试 »

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

示例

// 指向第二个元素
it = cars.begin() + 1;
自己尝试 »

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

示例

// 指向第三个元素
it = cars.begin() + 2;
自己尝试 »

End 示例

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

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

示例

// 指向最后一个元素
it = cars.end() - 1;
自己尝试 »

为什么我们说“指向”?

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

示例

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

// 修改第一个元素的值
*it = "Tesla";

// Volvo 现在是 Tesla
自己尝试 »

关键字auto

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

auto 关键字允许编译器自动确定正确的类型,从而简化代码并使其更具可读性。

而不是这样

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

你可以简单地写成这样

auto it = cars.begin();
自己尝试 »

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

auto 关键字也适用于 for 循环。

for (auto it = cars.begin(); it != cars.end(); ++it) {
  cout << *it << "\n";
}
自己尝试 »


For-Each 循环 vs. 迭代器

可以使用 **for-each** 循环遍历数据结构中的元素,例如

示例

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

// 打印向量元素
for (string car : cars) {
  cout << car << "\n";
}
自己尝试 »

当只需要读取元素而不修改它们时,for-each 循环比迭代器更简单、更简洁。

但是,如果需要在 **迭代期间** 添加、修改或删除元素,反向迭代或跳过元素,则应该使用迭代器。

示例

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

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

// 打印向量元素
for (const string& car : cars) {
  cout << car << "\n";
}
自己尝试 »

反向迭代

要反向迭代,可以使用 rbegin()rend(),而不是 begin()end()

示例

// 反向迭代
for (auto it = cars.rbegin(); it != cars.rend(); ++it) {
  cout << *it << "\n";
}
自己尝试 »

遍历其他数据结构

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

列表示例

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

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

双端队列示例

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

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

集合示例

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

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

映射示例

// 创建一个映射,用于存储字符串和整数
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 << "\n";
}
自己尝试 »

迭代器支持

上面的例子展示了如何遍历支持迭代器的不同数据结构(向量列表双端队列映射集合 支持迭代器,而 堆栈队列 不支持)。


算法

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

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

在本例中,元素按字母顺序排序,因为它们是字符串。

示例

#include <iostream>
#include <vector>
#include <algorithm>  // 包含 <algorithm> 库
using namespace std;

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

  // 按字母顺序对 cars 进行排序
  sort(cars.begin(), cars.end());

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

  return 0;
}
自己尝试 »

在本例中,元素按数字顺序排序,因为它们是整数。

示例

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

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

  // 按数字顺序对 numbers 进行排序
  sort(numbers.begin(), numbers.end());

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

  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};

  // 按反向数字顺序对 numbers 进行排序
  sort(numbers.rbegin(), numbers.rend());

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

  return 0;
}
自己尝试 »


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
[email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
[email protected]

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2024 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.