学懂C++(四十七):深入详解C++ STL之迭代器(Iterators)的应用

目录

1. 迭代器基本概念

2. 迭代器类型及其用法示例

2.1 输入迭代器(Input Iterator)

2.2 输出迭代器(Output Iterator)

2.3 前向迭代器(Forward Iterator)

2.4 双向迭代器(Bidirectional Iterator)

2.5 随机访问迭代器(Random Access Iterator)

3. 常见迭代器的高级操作

3.1 使用 std::advance 移动迭代器

3.2 使用 std::prev 和 std::next 获取前一个和后一个迭代器

总结


1. 迭代器基本概念

迭代器是用于遍历容器元素的对象,就像指针一样。根据功能的不同,迭代器可以分为五种类型:

  • 输入迭代器(Input Iterator):只能读取数据,支持单向遍历。
  • 输出迭代器(Output Iterator):只能写入数据,支持单向遍历。
  • 前向迭代器(Forward Iterator):支持读写操作,可以单向遍历。
  • 双向迭代器(Bidirectional Iterator):支持读写操作,可以双向遍历。
  • 随机访问迭代器(Random Access Iterator):支持读写操作,可以双向遍历,且支持随机访问。

2. 迭代器类型及其用法示例

2.1 输入迭代器(Input Iterator)

输入迭代器只能用于读取数据,典型的输入迭代器是 std::istream_iterator

底层原理

  • 输入迭代器可以读取数据,但不能修改它指向的数据。
  • 典型的输入迭代器是 std::istream_iterator,其底层原理是通过重载 operator* 和 operator++ 来实现读取流中的数据。
  • 它通过输入流(如 std::cin)来读取元素,每次读取一个元素,并将流的位置移动到下一个元素。

特点

  • 只能单向遍历。
  • 只能读取一次,不能重复读取。

示例

#include <iostream>
#include <iterator>
#include <vector>

int main() {
    std::cout << "Enter integers separated by spaces (Ctrl+D to end): ";
    std::istream_iterator<int> input_it(std::cin);  // 输入迭代器
    std::istream_iterator<int> end_of_stream;       // 输入流结束标志

    std::vector<int> vec(input_it, end_of_stream);  // 从输入流中读取数据并存入向量

    std::cout << "You entered: ";
    for (const auto& elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

2.2 输出迭代器(Output Iterator)

输出迭代器只能用于写入数据,典型的输出迭代器是 std::ostream_iterator

底层原理

  • 输出迭代器用于写入数据,不能读取它指向的数据。
  • 典型的输出迭代器是 std::ostream_iterator,其底层原理是通过重载 operator*operator++ 和 operator= 来实现将数据写入到输出流中。
  • 它通过输出流(如 std::cout)来写入元素,每次写入一个元素。

特点

  • 只能单向遍历。
  • 每个位置只能写入一次,不能读取已有的数据。

示例

#include <iostream>
#include <iterator>
#include <vector>

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

    std::cout << "Vector elements: ";
    std::ostream_iterator<int> output_it(std::cout, " ");  // 输出迭代器
    std::copy(vec.begin(), vec.end(), output_it);          // 将向量元素写入到标准输出

    std::cout << std::endl;
    return 0;
}

2.3 前向迭代器(Forward Iterator)

前向迭代器支持读写操作,可以单向遍历。标准库中的 std::forward_list 就是一个前向迭代器的例子。

底层原理

  • 前向迭代器可以读写数据,并且能单向遍历。
  • 容器如 std::forward_list 使用前向迭代器,其底层实现通常是一个单向链表。
  • 迭代器通过指针或引用来访问链表中的元素,并重载 operator* 和 operator++ 来遍历。

特点

  • 能读写数据。
  • 只能单向遍历。
  • 支持多次遍历同一序列。

示例

#include <iostream>
#include <forward_list>

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

    std::cout << "Forward list elements: ";
    for (auto it = flist.begin(); it != flist.end(); ++it) {
        std::cout << *it << " ";  // 通过解引用操作符访问元素
    }
    std::cout << std::endl;

    return 0;
}

2.4 双向迭代器(Bidirectional Iterator)

双向迭代器支持读写操作,可以双向遍历。典型的双向迭代器有 std::liststd::set

底层原理

  • 双向迭代器可以读写数据,并能双向遍历。
  • 容器如 std::list 和 std::set 使用双向迭代器,其底层实现通常是一个双向链表或平衡二叉树。
  • 迭代器通过指针或引用访问元素,并重载 operator*operator++operator-- 来遍历。

特点

  • 能读写数据。
  • 能前后遍历。
  • 支持多次遍历同一序列。

示例

#include <iostream>
#include <list>

int main() {
    std::list<int> lst = {10, 20, 30, 40, 50};

    std::cout << "List elements in forward order: ";
    for (auto it = lst.begin(); it != lst.end(); ++it) {
        std::cout << *it << " ";  // 向前遍历并访问元素
    }
    std::cout << std::endl;

    std::cout << "List elements in reverse order: ";
    for (auto it = lst.rbegin(); it != lst.rend(); ++it) {
        std::cout << *it << " ";  // 向后遍历并访问元素
    }
    std::cout << std::endl;

    return 0;
}

2.5 随机访问迭代器(Random Access Iterator)

随机访问迭代器支持读写操作,可以双向遍历,并且支持随机访问。常见的随机访问迭代器有 std::vectorstd::deque

底层原理

  • 随机访问迭代器可以读写数据,能双向遍历,并支持随机访问。
  • 容器如 std::vector 和 std::deque 使用随机访问迭代器,其底层实现通常是一个动态数组或分段数组。
  • 迭代器通过指针操作访问数组中的元素,并重载 operator*operator++operator--operator+operator-operator[] 来实现遍历和随机访问。

特点

  • 能读写数据。
  • 能前后遍历。
  • 支持随机访问。

示例

#include <iostream>
#include <vector>

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

    std::cout << "Vector elements: ";
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";  // 向前遍历并访问元素
    }
    std::cout << std::endl;

    std::cout << "Third element: " << vec[2] << std::endl;  // 随机访问第三个元素

    return 0;
}

3. 常见迭代器的高级操作

3.1 使用 std::advance 移动迭代器

std::advance 可以将迭代器移动指定的步数。

#include <iostream>
#include <vector>
#include <iterator>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto it = vec.begin();
    
    std::advance(it, 2);  // 将迭代器移动两个位置
    
    std::cout << "Element at position 3: " << *it << std::endl;

    return 0;
}

3.2 使用 std::prev 和 std::next 获取前一个和后一个迭代器

std::prevstd::next 可以用来获取相邻的迭代器。

#include <iostream>
#include <vector>
#include <iterator>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto it = vec.begin();
    std::advance(it, 2); // 移动到第三个位置
    
    // 使用 std::prev 获取前一个迭代器
    auto prev_it = std::prev(it);
    std::cout << "Previous element: " << *prev_it << std::endl;

    // 使用 std::next 获取后一个迭代器
    auto next_it = std::next(it);
    std::cout << "Next element: " << *next_it << std::endl;

    return 0;
}

总结

迭代器是 C++ STL 中非常重要的一部分,掌握它们的概念和用法可以大大提高代码的效率和可读性。希望这些详细注释的示例能帮助你更好地理解和应用迭代器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿享天开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值