STL——迭代器
迭代器Iterator简介迭代器是STL的核心组件它类似于指针提供了一种统一的方式来遍历容器中的元素。正是通过迭代器STL的容器如vector,list和算法如sort,find得以解耦。算法通过迭代器操作数据无需知道容器的具体类型。迭代器类别Iterator Categories为了使不同类型的迭代器能够支持不同的操作C 标准库将迭代器分为以下几种类别每种类别支持的操作能力逐级增强1、输入迭代器Input Iterator2、输出迭代器Output Iterator3、前向迭代器Forward Iterator4、双向迭代器Bidirectional Iterator5、随机访问迭代器Random Access Iterator6、无效迭代器Contiguous IteratorC20 引入每个类别都继承自前一个类别具备更强的功能。例如双向迭代器不仅支持前向迭代器的所有操作还支持反向迭代即可以向后移动。STL迭代器按功能分为五类从弱到强类型支持操作示例容器输入迭代器,*(只读一次)istream_iterator输出迭代器,*(只写一次)ostream_iterator前向迭代器,*(多次读写)forward_list双向迭代器,--,*list,map,set随机访问迭代器,--,*,,-,[]vector,deque,array无效迭代器新随机访问迭代器的所有功能且元素在内存中连续排列新的 C 容器如std::spanconst_iterator 与安全遍历cbegin()/cend()返回只读迭代器(const_iterator)。使用场景1、防止意外修改当只需读取时使用cbegin/cend相当于编译时保护2、通用编程在模板函数中如果希望始终只读遍历应使用cbegin()这样无论传入const或非const容器行为都一致安全。std::vectorint vec {1, 2, 3}; // 只读遍历安全 for (auto it vec.cbegin(); it ! vec.cend(); it) { // *it 5; // 错误不能修改 std::cout *it; }迭代器失效这是使用迭代器时最关键的问题之一。某些容器操作会使指向其元素的迭代器失效。以std::vector为例操作失效范围原因与示例尾部插入可能全部失效若触发重分配push_back导致容量不足重新分配内存。中间插入插入点之后的所有迭代器insert导致元素后移原有位置失效。删除删除点之后的所有迭代器erase导致元素前移。安全操作指南插入后重新获取迭代器insert会返回指向新元素的迭代器。删除时利用erase的返回值更新迭代器。std::vectorint v {1, 2, 3, 4, 5, 6}; for (auto it v.begin(); it ! v.end(); /* 这里不递增 */) { if (*it % 2 0) { it v.erase(it); // erase 返回下一个有效迭代器 } else { it; } }iterator_category的作用iterator_category是迭代器类型中的一个别名用于标识该迭代器所属的类别。它是标准库中迭代器特性Iterator Traits 的一部分标准算法会根据迭代器的类别优化其行为。为什么需要iterator_category标准库中的算法如std::sort、std::find等需要知道迭代器支持哪些操作以便选择最优的实现方式。例如对于随机访问迭代器可以使用快速的随机访问算法如快速排序。对于双向迭代器只能使用适用于双向迭代的算法如归并排序。对于输入迭代器只能进行单次遍历许多复杂算法无法使用。通过指定iterator_category你可以让标准算法了解你自定义迭代器的能力从而选择合适的方法进行操作。iterator_category的声明在你的自定义迭代器类中通过以下方式声明迭代器类别using iterator_category std::bidirectional_iterator_tag;这表示该迭代器是一个双向迭代器支持向前和向后遍历。std::bidirectional_iterator_tag详解std::bidirectional_iterator_tag是一个标签Tag用于标识迭代器类别。C 标准库中有多个这样的标签分别对应不同的迭代器类别std::input_iterator_tagstd::output_iterator_tagstd::forward_iterator_tagstd::bidirectional_iterator_tagstd::random_access_iterator_tagstd::contiguous_iterator_tagC20这些标签本质上是空的结构体用于类型区分。在标准算法中通常会通过这些标签进行重载选择Overload Resolution或特化Specialization以实现针对不同迭代器类别的优化。继承关系迭代器标签是有继承关系的std::forward_iterator_tag继承自std::input_iterator_tagstd::bidirectional_iterator_tag继承自std::forward_iterator_tagstd::random_access_iterator_tag继承自std::bidirectional_iterator_tagstd::contiguous_iterator_tag继承自std::random_access_iterator_tag这种继承关系反映了迭代器类别的能力层级。例如双向迭代器具备前向迭代器的所有能力加上反向遍历的能力。迭代器特性Iterator Traits详解C 提供了迭代器特性Iterator Traits通过模板类std::iterator_traits来获取迭代器的相关信息。通过这些特性标准算法可以泛化地处理不同类型的迭代器。迭代器特性包含的信息std::iterator_traits提供以下信息iterator_category迭代器类别标签。value_type迭代器指向的元素类型。difference_type迭代器间的距离类型通常是std::ptrdiff_t。pointer指向元素的指针类型。reference对元素的引用类型。自定义迭代器与iterator_traits当你定义自己的迭代器时确保提供这些类型别名以便标准库算法能够正确识别和使用你的迭代器。例如templatetypename T class Iterator { public: using iterator_category std::bidirectional_iterator_tag; using value_type T; using difference_type std::ptrdiff_t; using pointer T*; using reference T; // 其他成员函数... };这样使用std::iterator_traitsIteratorT时就能正确获取迭代器的特性。