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";
}
自己尝试 »
示例解释
- 首先,我们创建一个字符串向量来存储不同汽车制造商的名称。
- 然后,我们创建一个名为
it
的“向量迭代器”,我们将使用它来遍历向量。 - 接下来,我们使用
for
循环来使用迭代器遍历向量。迭代器 (it
) 指向向量中的第一个元素 (cars.begin()
),循环持续到it
不等于cars.end()
。 - 增量运算符 (
++it
) 将迭代器移动到向量中的下一个元素。 - 解引用运算符 (
*it
) 访问迭代器指向的元素。
注意:迭代器的类型必须与它应该遍历的数据结构的类型匹配(在本例中为string
)。
begin()
和 end()
是什么?
begin()
和 end()
是属于数据结构的函数,例如向量和列表。它们不属于迭代器本身。相反,它们与迭代器一起使用来访问和遍历这些数据结构的元素。
begin()
返回一个指向数据结构第一个元素的迭代器。end()
返回一个指向最后一个元素后面的一个位置的迭代器。
要了解它们的工作原理,让我们继续使用向量作为示例
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
vector<string>::iterator it;
Begin 示例
begin()
指向向量中的第一个元素(索引 0,即“Volvo”)。
要指向第二个元素(BMW),您可以写 cars.begin() + 1
。
当然,这意味着您也可以使用 cars.begin() + 2
指向第三个元素。
End 示例
end()
指向向量中最后一个元素之后的一个位置(这意味着它不指向实际元素,而是表示这是向量的末尾)。
因此,要使用end()
指向 cars 向量中的最后一个元素(Mazda),您可以使用cars.end() - 1
。
为什么我们说“指向”?
迭代器就像“指针”,它们“指向”数据结构中的元素,而不是从它们返回值。它们引用一个特定位置,提供了一种在需要时访问和修改值的方法,而无需复制它。例如
关键字auto
在 C++ 11 及更高版本中,可以使用 auto
关键字,而不是显式声明和指定迭代器的类型。
auto
关键字允许编译器自动确定正确的类型,从而简化代码并使其更具可读性。
而不是这样
vector<string>::iterator 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()
。
遍历其他数据结构
迭代器非常适合代码复用,因为可以使用相同的语法来遍历向量、列表、双端队列、集合和映射。
列表示例
// 创建一个名为 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;
}
自己尝试 »