一.迭代器介绍🍗
迭代器是 C++ 标准模板库(STL)中的一个重要概念。简单来说,迭代器就像是一个指针,用于访问和遍历容器中的元素(比如数组、链表、集合等)。迭代器提供了一种统一的方法来访问容器中的元素,而不需要关心容器的具体类型。
迭代器的主要作用包括:
1遍历容器: 通过迭代器可以遍历容器中的所有元素。例如,使用 begin() 和 end() 方法获取容器的起始和结束迭代器,然后通过循环来访问每个元素。
2访问元素: 可以通过迭代器读取或修改容器中的元素。
3连接算法与容器: STL 中的很多算法(如排序、查找等)都是通过迭代器来操作容器的。
应用场景示例
假设我们有一个 vector<int> 容器,存储了一些整数。我们可以使用迭代器来遍历这个 vector:
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
// 使用迭代器遍历 vector
for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
std::cout << *it << " ";
}
return 0;
}
这段代码会输出 vector 中的所有元素。迭代器 it 在每次循环中都指向 vector 的下一个元素,直到达到 end()。这样的遍历方法比较通用,不依赖于容器的具体类型,这是迭代器的一个重要优势。
二.五种迭代器类型🍗
C++ STL 中有五种主要的迭代器类型,它们分别是:
1:输入迭代器(Input Iterators): 这种迭代器用于从容器中读取数据。它只支持单向遍历,即只能向前移动(通过 ++ 操作符)。输入迭代器只能进行一次读取,读取后迭代器就会前进到下一个元素。
2:输出迭代器(Output Iterators): 与输入迭代器相反,输出迭代器用于向容器中写入数据。它同样只支持单向遍历,且只能进行一次写入操作,写入后迭代器会自动前进到下一个位置。
3前向迭代器(Forward Iterators): 前向迭代器类似于输入和输出迭代器,但它支持多次读写操作。它也只能单向遍历,但可以对同一个元素进行多次访问。
3前向迭代器(Forward Iterators): 前向迭代器类似于输入和输出迭代器,但它支持多次读写操作。它也只能单向遍历,但可以对同一个元素进行多次访问。
4:双向迭代器(Bidirectional Iterators): 如其名,双向迭代器可以在容器中向前和向后移动。它扩展了前向迭代器的功能,使得迭代器可以使用 -- 操作符向前移动。双向迭代器在像 list 和 set 这样的容器中非常有用。
5:随机访问迭代器(Random Access Iterators): 这是最强大的迭代器类型,它支持所有前面提到的迭代器的功能,并且能够进行随机访问。这意味着除了能够向前和向后移动,随机访问迭代器还能够直接跳跃到任意位置(如通过 + 或 - 操作符)。vector 和 deque 容器提供了随机访问迭代器。
这些迭代器类型构成了 STL 设计的基础,使得 STL 算法可以在不同类型的容器上以统一的方式工作。不同类型的迭代器提供了不同级别的功能和灵活性,使得我们可以根据需要选择合适的迭代器类型来操作容器。
三.迭代器的失效🍗
迭代器失效指的是当容器发生变化时,之前获取的迭代器不再指向有效的元素或者不再有意义,这种情况在 C++ STL 编程中比较常见。迭代器失效主要发生在以下几种情况:
1.元素被删除或修改: 如果你删除了某个迭代器所指向的元素,那么这个迭代器就失效了。例如,在使用 vector 或 list 的 erase 方法删除元素后,指向被删除元素的迭代器会失效。
2.容器被重新分配: 对于某些容器(如 vector),如果容量被重新分配(比如在添加元素时容量不足以容纳更多元素),那么指向容器内元素的所有迭代器、引用和指针都将失效。
3.插入元素: 对于某些容器,如 vector 和 deque,在中间位置插入元素可能会导致指向插入位置之后元素的迭代器失效。
应对迭代器失效
1.谨慎操作: 在修改容器时,要小心处理迭代器。比如,在删除元素后,不要使用指向被删除元素的迭代器。
1.谨慎操作: 在修改容器时,要小心处理迭代器。比如,在删除元素后,不要使用指向被删除元素的迭代器。
2.更新迭代器: 某些操作(如 insert 和 erase)会返回一个新的迭代器,指向特定的元素。可以使用这些新的迭代器来继续操作。
3.避免在循环中修改容器: 尽量避免在遍历容器的同时对其进行修改。如果需要这样做,可以使用新的迭代器来代替之前的迭代器。
例子
假设你有一个 vector<int>,并且正在遍历它:
假设你有一个 vector<int>,并且正在遍历它:
在这个例子中,删除元素 3 后,it 迭代器失效了。继续使用这个迭代器可能会导致未定义行为。正确的做法是使用 erase 返回的新迭代器来继续遍历。
std::vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); ++it) {
if (*it == 3) {
v.erase(it);
// 此时 it 已经失效,再使用它将是不安全的
}
}
本篇完!🍗