C++ 迭代器
C++ 迭代器
迭代器用于通过"指向"元素来访问和遍历数据结构(向量、集合等)中的元素。
之所以称为"迭代器",是因为"迭代"是循环的技术术语。
以下是通过迭代器遍历向量的示例:
实例
// 创建存储字符串的向量 cars vector<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; // 创建向量迭代器 it vector<string>::iterator it; // 使用迭代器遍历向量 for (it = cars.begin(); it != cars.end(); ++it) { cout << *it << "\n"; }
例子解释:
- 首先创建存储汽车品牌名称的字符串向量
- 然后创建名为 "
it
" 的向量迭代器用于遍历 - 使用
for
循环配合迭代器遍历向量。迭代器 (it
) 指向向量第一个元素 (cars.begin()
),循环持续直到迭代器不等于cars.end()
- 递增运算符 (
++it
) 将迭代器移动到向量中的下一个元素 - 解引用运算符 (
*it
) 访问迭代器指向的元素
注意:迭代器的类型必须与其遍历的数据结构类型匹配(本例中为 string
)
begin() 和 end() 函数
begin()
和 end()
是属于数据结构(如向量和列表)的成员函数,它们不属于迭代器本身,而是与迭代器配合使用来访问和遍历数据结构元素。
begin()
返回指向数据结构第一个元素的迭代器end()
返回指向最后一个元素之后位置的迭代器
继续以向量为例说明它们的工作原理:
vector<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; 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()
指向向量中最后一个元素之后的位置(不指向实际元素,仅表示向量结束)。
因此,要指向 cars 向量的最后一个元素 (Tesla),可以使用 cars.end() - 1
:
实例
// 指向最后一个元素 it = cars.end() - 1;
为什么说"指向"?
迭代器类似于"指针",它们"指向"数据结构中的元素而不是返回元素值。它们引用特定位置,提供访问和修改值的方式,而无需复制值。例如:
实例
// 指向向量第一个元素 it = cars.begin(); // 修改第一个元素的值 *it = "Audi"; // Volvo 现在变为 Audi
auto 关键字
在 C++11 及更高版本中,可以使用 auto
关键字代替显式声明和指定迭代器类型。
auto
关键字让编译器自动确定正确的数据类型,简化代码并提高可读性:
替代这种写法:
vector<string>::iterator it = cars.begin();
可以简写为:
auto it = cars.begin();
在上面的例子中,编译器根据 cars.begin()
的返回类型(即 vector<string>::iterator
)自动推导出 it
的类型。
在 for
循环中也可以使用 auto
关键字:
for (auto it = cars.begin(); it != cars.end(); ++it) { cout << *it << "\n"; }
for-each 循环 vs 迭代器
可以使用 for-each 循环遍历数据结构元素:
实例
// 创建存储字符串的向量 cars vector<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; // 打印向量元素 for (string car : cars) { cout << car << "\n"; }
但当需要在迭代过程中添加/删除元素、反向迭代或跳过元素时,应该使用迭代器:
实例
// 创建存储字符串的向量 cars vector<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; // 遍历向量元素 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),用于存储字符串 list<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; // 使用迭代器遍历链表 for (auto it = cars.begin(); it != cars.end(); ++it) { cout << *it << "\n"; }
双端队列实例
// 创建一个名为 cars 的双端队列 (deque),用于存储字符串 deque<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; // 使用迭代器遍历双端队列 for (auto it = cars.begin(); it != cars.end(); ++it) { cout << *it << "\n"; }
集合实例
// 创建一个名为 cars 的集合 (set),用于存储字符串 set<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; // 使用迭代器遍历集合 for (auto it = cars.begin(); it != cars.end(); ++it) { cout << *it << "\n"; }
映射实例
// 创建一个映射 (map),用于存储字符串到整数的键值对 map<string, int> people = { {"Bill", 19}, {"Steve", 32}, {"Elon", 26} }; // 使用迭代器遍历映射 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> // 包含算法库 using namespace std; int main() { // 创建一个存储字符串的 vector 容器,名为 cars vector<string> cars = {"Volvo", "BMW", "Ford", "Tesla"}; // 对 cars 中的元素按字母顺序进行排序 sort(cars.begin(), cars.end()); // 按字母顺序打印排序后的汽车品牌 for (string car : cars) { cout << car << "\n"; } return 0; }
下例对整数元素进行数值排序:
实例
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { // 创建一个整型 vector 容器,名为 numbers,并初始化 6 个整数 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() { // 创建一个整型 vector 容器 numbers,初始化 6 个整数 vector<int> numbers = {1, 7, 3, 5, 9, 2}; // 使用 rbegin() 和 rend() 反向迭代器实现降序排列 sort(numbers.rbegin(), numbers.rend()); for (int num : numbers) { cout << num << "\n"; } return 0; }