std::prev 和 std::next 是 C++11 引入的迭代器偏移函数,仅支持双向及以上迭代器;std::next(it,n) 向后偏移 n 步(n≥0),std::prev(it,n) 向前偏移 n 步,均不修改原迭代器且不检查越界。

std::prev 和 std::next 是什么,不是指针偏移
它们是 C++11 引入的迭代器偏移工具函数,不是运算符重载,也不直接操作指针。关键点在于:它们只对满足 LegacyBidirectionalIterator 或更强概念(如 RandomAccessIterator)的迭代器有效。对 std::list::iterator 调用 std::next(it, 10) 会做 10 次 ++it,不是 O(1);而对 std::vector::iterator 则是 O(1) —— 这个差异直接影响性能判断。
std::prev/next 的参数陷阱:第二个参数不能是负数
常见错误是把 std::prev(it, -3) 当作“向前 3 步”,实际会编译失败:error: no matching function for call to 'prev(..., int)'。因为它的第二个参数类型是 typename iterator_traits<iterator>::difference_type</iterator>,但重载只接受非负整数。想反向走,必须显式调用 std::prev,而不是传负数给 std::next:
auto it = vec.begin(); auto it2 = std::next(it, 5); // OK: 向后 5 auto it3 = std::prev(it, 5); // OK: 向前 5 auto it4 = std::next(it, -5); // ❌ 编译错误
和算术运算符 ++/-- 或 += 的区别在哪
主要在语义安全和泛型适配性上:
-
std::next(it, n)返回新迭代器,不修改原it;it += n直接改原变量,且仅对RandomAccessIterator合法 -
std::prev(it)对所有双向迭代器都安全;--it虽等价,但写成std::prev(it)更清晰表达“取前一个”的意图,尤其在模板代码中利于静态分析 - 对输入迭代器(如
std::istream_iterator),std::next可能合法(取决于实现),但+=或+一定不合法
容易被忽略的边界问题:越界不检查
std::prev 和 std::next 完全不验证是否越界。传入 begin() 再调 std::prev,或者传 end() 再调 std::next,行为未定义 —— 不抛异常,不报错,可能崩溃或读到垃圾值。
立即学习“C++免费学习笔记(深入)”;
使用前必须自己确保范围安全:
- 用
std::distance预判距离(注意性能:对双向迭代器是 O(n)) - 对容器,优先用
c.begin() + n(随机访问)或std::advance(需就地修改时) - 真实项目中,更推荐封装一层带断言的辅助函数,比如
safe_next(it, n, c.end())
最常出问题的地方,是把 std::prev(c.end()) 当作最后一个元素,却忘了容器为空时 c.end() == c.begin(),此时 std::prev(c.end()) 就越界了。











