迭代器必须实现5个typedef(value_type等)和5个操作符(*、->、++、==、!=);支持sort需额外随机访问操作;iterator_category依底层结构选择;const迭代器需分离类型并const重载begin/end;operator!=须显式定义。

迭代器必须实现哪些成员类型和操作符
STL 容器的算法(比如 std::sort、std::for_each)依赖迭代器提供标准接口,不是“能跑就行”。漏掉任意一个关键成员类型或操作符重载,编译器会在泛型调用处报错,常见如:error: no match for 'operator!=' 或 no type named 'difference_type'。
最小可行集包括:
-
value_type、difference_type、pointer、reference、iterator_category—— 这 5 个 typedef 缺一不可 - 必须重载:
operator*、operator->、operator++(前置)、operator==和operator!= - 若想支持
std::sort等算法,还得加operator+、operator-、operator[]和随机访问比较(取决于iterator_category)
iterator_category 怎么选:input_iterator_tag 还是 random_access_iterator_tag
这个类型决定了你的迭代器能用哪些 STL 算法。选错会导致编译失败或静默退化(比如本该 O(1) 的 std::distance 变成 O(n))。
判断依据不是“我想让它多快”,而是“底层数据结构是否支持常数时间跳转”:
立即学习“C++免费学习笔记(深入)”;
- 数组、vector 底层:用
std::random_access_iterator_tag - 链表、文件流、生成器类:只能用
std::input_iterator_tag或std::forward_iterator_tag - 别硬凑
random_access_iterator_tag—— 即使你实现了operator+,但内部是链式遍历,std::sort会反复调用它,性能崩塌
示例:一个包装 std::vector<int></int> 的只读迭代器,iterator_category 必须是 std::random_access_iterator_tag;而一个按规则生成斐波那契数的迭代器,只能是 std::input_iterator_tag。
const 迭代器怎么写才不和非 const 版本冲突
用户会同时写 auto it = c.begin() 和 auto it = c.cbegin(),这两者必须能共存,且不能靠返回类型“猜”——C++ 不允许仅靠返回值重载函数。
正确做法是:把 begin() / end() 声明为 const 成员函数,并在 const 对象上调用时返回 const 迭代器类型:
- 定义两个迭代器类:
iterator和const_iterator,后者通常复用前者模板(用using const_iterator = iterator<const t></const>) -
begin()在非 const 对象上返回iterator,在 const 对象上返回const_iterator(靠 const 重载区分) - 别偷懒只写一个迭代器类然后用
const T*模板参数应付——std::vector::iterator和std::vector::const_iterator是不同类型,STL 算法靠类型做 SFINAE 分发
operator!= 为什么不能只靠 operator== 实现
很多新手写 bool operator!=(const self& other) const { return !(*this == other); },看似省事,但 STL 中部分算法(如 std::find_if)在 C++20 前明确要求 operator!= 是独立可调用的,且某些标准库实现(尤其是 MSVC 的 debug 模式)会直接检查该符号是否存在,不走 fallback。
更关键的是语义安全:如果 operator== 有副作用或抛异常,operator!= 就不该隐式复用它。
- 务必显式定义
operator!=,内容可以和operator==对称(比如比较指针/索引) - 不要依赖 ADL 或隐式转换——确保两个操作符都在迭代器类内部定义,或作为友元
- 测试时用
static_assert(std::is_same_v<decltype>() != std::declval<it>()), bool>);</it></decltype>验证
自定义迭代器真正难的不是语法,是让每个 typedef、每个操作符的行为和 STL 内置迭代器对齐——差一点,std::copy 就可能静默复制错误字节数,或者 std::lower_bound 直接进入无限循环。








