C++ 迭代器iterator

一、迭代器简介

在 C++ 中,迭代器(iterator)是一种通用的抽象概念,用于在容器(如 std::vectorstd::liststd::map 等)中遍历和访问元素。迭代器提供了一种统一的接口,使得不同类型的容器可以以相似的方式进行遍历和操作。

大多数 C++ 容器都提供了迭代器,用于遍历容器中的元素。例如,std::vectorstd::deque 提供了随机访问迭代器,std::list 提供了双向迭代器,std::setstd::map 提供了双向迭代器。

二、迭代器分类

迭代器类似于指针,可以通过解引用(dereferencing)来访问指向的元素,并且可以通过递增或递减操作符进行移动。C++ 标准库提供了多种类型的迭代器,它们根据支持的操作和特性可分为以下几类:

  1. 输入迭代器(Input Iterator):只读迭代器,支持前向移动、解引用、相等/不等比较。适用于单遍扫描的算法。
  2. 输出迭代器(Output Iterator):只写迭代器,支持前向移动和解引用赋值。适用于单遍输出的算法。
  3. 前向迭代器(Forward Iterator):支持读写操作,只能前向移动。适用于多遍扫描的算法。
  4. 双向迭代器(Bidirectional Iterator):支持读写操作,可以前向和后向移动。适用于需要反向遍历的算法。
  5. 随机访问迭代器(Random Access Iterator):支持读写操作,可以进行任意跳跃。适用于需要随机访问的算法。

三、迭代器使用

容器类提供了一些方法来获取和操作迭代器,例如:

  1. begin():返回指向容器中第一个元素的迭代器。
  2. end():返回指向容器中最后一个元素之后的迭代器。
  3. rbegin():返回指向容器中最后一个元素的逆向迭代器(仅双向迭代器和随机访问迭代器的容器)。
  4. rend():返回指向容器中第一个元素之前的逆向迭代器(仅双向迭代器和随机访问迭代器的容器)。

当我们需要遍历容器时,可以使用容器提供的这些方法来获取迭代器,然后用迭代器来访问和操作容器中的元素。

以下是一个使用 std::vector 的迭代器遍历容器的例子:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用 auto 关键字简化迭代器类型声明
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << std::endl; // 输出 numbers 容器中的每个元素
    }

    return 0;
}

在这个例子中,numbers.begin() 返回指向容器中第一个元素的迭代器,numbers.end() 返回指向容器中最后一个元素之后的迭代器。通过递增迭代器 ++it,我们可以遍历容器中的所有元素。

四、迭代器原理

迭代器对象与容器相关联的原因在于迭代器对象的设计和实现。迭代器对象通常会存储与特定容器实例相关的信息,如指向容器中的某个元素的指针或者其他表示当前位置的数据。通过这些信息,迭代器对象可以在容器中定位和访问元素。虽然迭代器对象本身是独立的,但它与特定容器实例密切相关,因为它需要知道容器的内部结构以执行遍历和访问操作。

当你使用容器的成员函数(如 begin()end() 等)获取迭代器时,这些函数会创建一个与容器实例关联的迭代器对象。这个迭代器对象存储了足够的信息,以便在容器内遍历元素。

std::vector 为例,当你调用 std::vector<T>::begin() 时,它会返回一个指向容器中第一个元素的迭代器。这个迭代器内部通常包含一个指向第一个元素的指针。当你对迭代器执行递增操作(如 ++it)时,这个指针会根据容器内元素的布局和类型进行移动,从而指向下一个元素。这样,迭代器就能够根据容器的结构进行遍历和访问操作。

需要注意的是,迭代器与容器的关联是在运行时建立的,因此迭代器对象需要与创建它的容器保持同步。如果在迭代器存在的过程中容器发生改变(如添加、删除元素等),可能会导致迭代器失效。在这种情况下,继续使用失效的迭代器可能会导致未定义的行为。因此,在使用迭代器时要确保正确处理这些情况,如在容器发生改变时及时更新迭代器。

猜你喜欢

转载自blog.csdn.net/2201_75772333/article/details/130618990