operator++需区分前置与后置:前置返回引用,后置返回旧值副本;C++用空参数列表强制区分;常见错误包括后置返回引用或未正确调用前置。

为什么 operator++ 要区分前置和后置?
因为语义不同:前置 ++it 应返回引用,后置 it++ 必须返回旧值的副本。C++ 用空参数列表区分后置——这是硬性约定,不是可选风格。
常见错误是只实现一个版本,或后置返回引用(导致悬垂引用),或忘了后置内部调用前置再递减(逻辑错乱)。
- 前置:直接修改
this,return *this; - 后置:先保存当前状态,调用前置,再返回保存的副本(注意拷贝成本)
- 如果迭代器持有裸指针或轻量结构体(如
int*、std::array<t n>::iterator</t>),后置返回值可 cheap;否则考虑是否真需支持后置
iterator_category 该设成什么?
它决定算法能否使用该迭代器,比如 std::sort 要求 random_access_iterator_tag,而 std::find 只要 input_iterator_tag 就够了。设错会导致编译失败或退化为低效路径。
别凭感觉写,按实际能力选:
立即学习“C++免费学习笔记(深入)”;
- 只能读一次、单向移动 →
std::input_iterator_tag - 可多次遍历、单向 →
std::forward_iterator_tag - 支持
--it→std::bidirectional_iterator_tag - 支持
it + n、it[n]、it1 - it2→std::random_access_iterator_tag - C++20 起还可选
std::contiguous_iterator_tag(要求元素内存连续)
怎么让自定义迭代器兼容范围 for?
关键不是迭代器本身,而是你容器的 begin() 和 end() 成员函数必须存在且返回正确类型。编译器在 for (auto& x : container) 中会自动查找这两个函数。
容易被忽略的点:
- 必须声明为
const重载:非 const 容器调begin(),const 容器必须能调begin() const,否则const Container c; for (auto x : c)编译不过 - 返回类型建议用
using iterator = MyIterator<t>;</t>并统一 typedef,避免模板推导失败 - 若迭代器模板参数依赖容器(如
MyContainer::iterator),确保MyContainer的iterator类型别名已正确定义
C++20 概念下要不要手动写 operator==?
要,而且不能省。C++20 范围库(如 std::ranges::find)默认要求迭代器满足 std::equality_comparable,即必须可比较相等。仅靠 operator!= 不足以满足该概念。
典型陷阱:
- 只写了
operator!=,结果std::ranges::find编译报错:“constraints not satisfied” - 用
std::default_order_fallback或 ADL 试图绕过,反而引发二义性 - 比较逻辑不一致:比如
operator==比较指针,但operator!=比较封装的索引字段
最稳妥做法:显式定义 friend bool operator==(const MyIter& a, const MyIter& b),内容与 operator!= 逻辑严格互补。
复杂点在于,如果你的迭代器需要支持异构比较(如 MyIter == std::vector<t>::iterator</t>),那就得额外加友元声明和 SFINAE 控制——这种需求极少,多数情况只做同类型比较就够了。


















