别人没那么重要,我也没那么重要,好好活着,把能做的小事做好,够不到的东西就放弃,承认就好。做一个心情好能睡着的人,你所有事情都会在正轨上。

【C++】标准模板库STL-迭代器

  在C++标准模板库(STL)中,迭代器(Iterators)是一类对象,它们提供了一种统一的接口来遍历和元素进行交互。迭代器可以被视为一种泛化的指针,它们允许程序员在不知道底层容器实现细节的情况下,对容器中的元素进行访问和操作。

  迭代器是STL的基石之一,因为它们允许算法与容器进行解耦,这意味着同一个算法可以用于不同的容器类型。

1. 迭代器特性

  • 迭代器是对象:迭代器本身是对象,可以存储当前遍历到的位置的状态。
  • 迭代器是轻量级:迭代器通常不复制容器中的元素,而是提供一个访问容器元素的途径。
  • 迭代器是可变的:迭代器可以改变其所指向的元素的值。

2. 迭代器分类

  1. 输入迭代器(Input Iterators)
    • 允许你读取每个元素一次,用于流式的输入。
    • 支持 ++ 递增操作和相等性比较。
    • 只能进行元素的读取,不支持元素的写入。
  1. 输出迭代器(Output Iterators)
    • 主要用于写入序列,如 std::copy 的输出参数。
    • 支持 ++ 递增操作和相等性比较,以及元素的写入。
  1. 前向迭代器(Forward Iterators)
    • 结合了输入和输出迭代器的特性,允许多次读取和写入。
    • 支持单向遍历,只能前进不能后退。
  1. 双向迭代器(Bidirectional Iterators)
    • 扩展了前向迭代器,允许元素的双向遍历(前进和后退)。
    • 支持 -- 递减操作,可以向后移动到前一个元素。
  1. 随机访问迭代器(Random Access Iterators)
    • 双向迭代器加上随机访问能力,可以快速跳转到任意位置。
    • 支持所有的算术操作,如 +, -, +=, -=,以及比较操作 >, <, >=, <=
  1. 容器适配器迭代器(Container Adaptor Iterators)
    • 例如 std::stack, std::queue, 和 std::priority_queue 提供的迭代器。
    • 这些迭代器的行为依赖于适配器的实现,通常限制了迭代器的操作范围。
  1. 代码示例:
     1 std::vector<int> vec = {1, 2, 3, 4, 5};
     2 std::vector<int>::iterator it = vec.begin(); // 随机访问迭代器
     3 
     4 // 随机访问迭代器操作
     5 it += 2;        // 跳转到第三个元素
     6 it -= 1;        // 跳转到第四个元素
     7 int val = it[2]; // 访问第六个元素(从零开始计数)
     8 
     9 std::list<int> lst = {1, 2, 3, 4, 5};
    10 std::list<int>::iterator lit = lst.begin(); // 前向迭代器
    11 
    12 // 前向迭代器操作
    13 ++lit; // 移动到下一个元素
    14 lit++; // 移动到下一个元素(后置递增)

3. 迭代器操作

  • 解引用操作符(*):访问迭代器指向的元素。
  • 成员访问操作符(->):通过迭代器访问对象的成员。
  • 前缀递增(++)和后缀递增(++):将迭代器移动到下一个元素。
  • 前缀递减(--)和后缀递减(--):将迭代器移动到上一个元素。
  • 相等和不相等操作符(==, !=):比较两个迭代器是否相等或不相等。

4. 示例代码

在C++ STL中,迭代器允许你以统一的方式访问和操作容器中的元素。以下是一些常见的迭代器操作:

4.1. 迭代器初始化

1 std::vector<int> vec = {1, 2, 3, 4, 5};
2 std::vector<int>::iterator it; // 声明迭代器

4.2. 遍历容器

1 for (it = vec.begin(); it != vec.end(); ++it) {
2     // *it 访问当前元素
3     // it->member 访问当前元素的成员变量
4 }

4.3. 直接访问元素

1 auto val = *it; // 获取当前迭代器指向的元素的值

4.4. 递增和递减迭代器

1 ++it; // 前置递增
2 it++; // 后置递增
3 --it; // 前置递减
4 it--; // 后置递减

4.5. 比较迭代器

1 if (it == vec.begin()) {
2     // it 指向容器的开始
3 }
4 
5 if (it != vec.end()) {
6     // it 不是容器的结束
7 }

4.6. 随机访问迭代器(如 std::vectorstd::array

1 std::vector<int>::iterator it = vec.begin() + 2; // 直接跳转到第三个元素

4.7. 使用 std::advance 函数

1 std::advance(it, 3); // 将迭代器向前移动3个位置

4.8. 范围基 for 循环(C++11及以后)

1 for (auto& val : vec) {
2     // val 是容器中的元素的引用
3 }

4.9. 使用迭代器访问容器元素的成员

1 struct Node {
2     int value;
3     // ...
4 };
5 
6 std::vector<Node> nodes;
7 for (auto& node : nodes) {
8     node.value = 1; // 直接修改当前节点的 value 成员
9 }

4.10. 迭代器失效

  在某些操作(如插入、删除、重新分配)后,迭代器可能会失效。因此,需要谨慎地管理迭代器的生命周期。

1 vec.erase(it); // 删除当前迭代器指向的元素后,该迭代器失效

4.11. 注意

  • 迭代器的类型应与容器类型匹配。
  • 迭代器操作应该在容器的有效期内。
  • 某些容器操作可能导致迭代器失效,例如 eraseclear 或容器的重新分配。
  • 迭代器的比较和算术操作取决于迭代器的类别(如输入迭代器、前向迭代器、随机访问迭代器等)。

 

时间:2024年5月1日

 

posted @ 2024-05-01 10:31  一路狂奔的乌龟  阅读(106)  评论(0)    收藏  举报
返回顶部