前置知识: C

C++ STL 迭代器

1 min入门

C++ STL 迭代器 的完整教学讲解。

迭代器类别

基本写法:输入迭代器 std::input_iterator<T>

// 只读、单遍递增,如 istream_iterator
std::istream_iterator<int> it(std::cin), end;
while (it != end) { std::cout << *it++; }

基本写法:前向迭代器 std::forward_iterator<T>

// 只读或多遍递增,如 forward_list 的迭代器
std::forward_list<int> l{1, 2, 3};
for (auto it = l.begin(); it != l.end(); ++it) { *it += 1; }

基本写法:双向迭代器 std::bidirectional_iterator<T>

// 支持递减,如 list/set/map 的迭代器
std::list<int> l{1, 2, 3};
auto it = l.end(); --it; // 指向 3

基本写法:随机访问迭代器 std::random_access_iterator<T>

// 支持 + n / - n 与下标,如 vector/deque/array
std::vector<int> v{10, 20, 30};
auto it = v.begin() + 2; // 指向 30

基本写法:连续迭代器(C++20) std::contiguous_iterator<T>

// 元素连续存储,最强保证,如 vector/array
int* p = v.data(); // 等价裸指针访问

容器迭代器

基本写法:begin/end <容器>.begin() / <容器>.end()

// 返回首元素与尾后位置迭代器
std::vector<int> v{1, 2, 3};
for (auto it = v.begin(); it != v.end(); ++it) { std::cout << *it; }

基本写法:只读迭代器 <容器>.cbegin() / <容器>.cend()

// const 版本,元素不可修改
for (auto it = v.cbegin(); it != v.cend(); ++it) { /* *it = 0; 错误 */ }

基本写法:反向迭代器 <容器>.rbegin() / <容器>.rend()

// 反向遍历,rbegin 指向末元素
for (auto it = v.rbegin(); it != v.rend(); ++it) { std::cout << *it; }

基本写法:自由函数版本 std::begin(<容器>) / std::end(<容器>)

// 适配原生数组与容器
int arr[] = {1, 2, 3};
auto total = std::accumulate(std::begin(arr), std::end(arr), 0);

迭代器辅助函数

基本写法:距离 std::distance(<首>, <尾>)

// 计算两个迭代器间距离
auto n = std::distance(v.begin(), v.end()); // 元素个数

基本写法:前进 std::advance(<迭代器>, <步数>)

// 原地移动迭代器,负数需双向或随机访问
auto it = v.begin();
std::advance(it, 2); // 指向第 3 个元素

基本写法:移动到下一位置 std::next(<迭代器> [, <步数>])

// 返回前进后的副本,不修改原迭代器
auto it = std::next(v.begin()); // 指向第 2 个元素
auto it2 = std::next(v.begin(), 2);

基本写法:移动到上一位置 std::prev(<迭代器> [, <步数>])

// 返回后退后的副本,需双向迭代器
auto it = std::prev(v.end()); // 指向末元素

插入迭代器

基本写法:尾插迭代器 std::back_inserter(<容器>)

// 每次赋值调用 push_back
std::vector<int> dst;
std::copy(v.begin(), v.end(), std::back_inserter(dst));

基本写法:头插迭代器 std::front_inserter(<容器>)

// 每次赋值调用 push_front,需有该接口
std::list<int> dst;
std::copy(v.begin(), v.end(), std::front_inserter(dst));

基本写法:任意位置插入迭代器 std::inserter(<容器>, <位置>)

// 在指定位置前插入
auto it = std::inserter(dst, dst.begin());

基本写法:移动迭代器 std::make_move_iterator(<迭代器>)

// 将解引用转为右值引用,触发移动
std::vector<std::string> v2(std::make_move_iterator(v.begin()),
                           std::make_move_iterator(v.end()));

流迭代器

基本写法:输入流迭代器 std::istream_iterator<T>(<流>)

// 从输入流读取 T 序列
std::vector<int> v2((std::istream_iterator<int>(std::cin)),
                    std::istream_iterator<int>());

基本写法:输出流迭代器 std::ostream_iterator<T>(<流> [, <分隔串>])

// 将元素写入输出流
std::copy(v.begin(), v.end(),
          std::ostream_iterator<int>(std::cout, ", "));

C++20 哨兵与范围

基本写法:哨兵判断结束 <范围>.end() 可与迭代器不同类型

// C++20 允许 end() 返回哨兵类型,如 read_until_eof 的结束判断
// 算法用 == 比较迭代器与哨兵

基本写法:ranges 迭代器 std::ranges::begin(<范围>)

// 范式库的迭代器接口,返回第一元素
auto it = std::ranges::begin(v);
auto end = std::ranges::end(v);

基本写法:view 迭代 for (auto&& <x> : <视图>)

// 视图是惰性迭代的轻量范围
auto even = v | std::views::filter([](int x){ return x % 2 == 0; });
for (int x : even) { std::cout << x; }

自定义迭代器

基本写法:迭代器特征别名 std::iterator_traits<<迭代器类型>>

// 提取 value_type/difference_type/pointer/reference
using traits = std::iterator_traits<std::vector<int>::iterator>;
traits::value_type n = 0;

基本写法:C++20 概念约束迭代器 std::input_iterator<I>

#include <iterator>
// 用 concept 约束模板迭代器类型
template <std::input_iterator It>
auto sum(It first, It last) {
    return std::accumulate(first, last, 0);
}