std::adjacent_find 查不到重复元素通常因谓词逻辑错误:默认用 operator== 比较相邻元素,自定义谓词须返回 true 表示“相等”;若误写为 a > b 则查找递减对而非重复值。

std::adjacent_find 查不到重复元素?检查比较逻辑是否默认或自定义错
默认行为只比较相邻两个元素是否相等,如果用自定义谓词但返回了 false 表示“相等”,就会完全反向匹配。常见错误是把谓词写成 a > b 却期望它找重复值——这实际在找递减对。
- 不传谓词时,内部调用
operator==,要求类型支持该操作符 - 传谓词时,函数找的是满足
pred(*it, *(it+1)) == true的第一对相邻元素;若想找相等,谓词必须写成[](const auto& a, const auto& b) { return a == b; } - 对
std::vector<:string></:string>等类型,大小写敏感比较需显式传std::equal_to()或自定义忽略大小写的 lambda
返回迭代器失效的典型场景:容器被修改后继续解引用
std::adjacent_find 返回的是正向迭代器(如 std::vector::iterator),一旦容器发生插入、删除、reserve 或 resize,该迭代器立即失效。最常踩的坑是查到位置后直接存为裸指针或长期缓存。
- 安全做法:查完立刻使用,比如
if (auto it = std::adjacent_find(v.begin(), v.end()); it != v.end()) { /* 处理 *it 和 *(it+1) */ } - 不要写
auto pos = std::adjacent_find(...); v.push_back(x); use(*pos);—— 此时pos已无效 - 若需记录位置并延后处理,改用下标索引(
it - v.begin()),前提是容器不重分配
在 list 和 forward_list 上性能差异大吗?
算法本身是线性遍历,与容器底层无关,但实际性能受迭代器类型影响:std::list 的双向迭代器支持 ++ 和 --,没问题;std::forward_list 的前向迭代器只能 ++,而 std::adjacent_find 内部只需单向移动,所以完全兼容且无额外开销。
- 所有标准序列容器(
vector、deque、list、forward_list)和关联容器(set等)都可用,只要提供符合要求的迭代器 - 注意:
std::array和原始数组也支持,传入arr和arr + N即可 - 对
forward_list,不能用it + 1,但std::adjacent_find内部用的是std::next(it),已适配
找不到时返回 end(),但容易误判空容器
当容器元素数 std::adjacent_find 直接返回 end(),不报错也不抛异常。新手常忽略这个前提,直接对返回值做 *(it + 1) 导致越界。
立即学习“C++免费学习笔记(深入)”;
- 正确判断方式只有:
if (it != container.end()),别用it == container.begin()或it == nullptr - 对空容器或单元素容器,调用是合法的,结果确定为
end() - 若逻辑上要求至少两个元素才搜索,建议前置检查:
if (v.size()
复杂点在于谓词语义和迭代器生命周期的耦合——它不报错,但一错就静默 UB;最容易被忽略的是:哪怕你只读容器,只要用了 std::vector::emplace_back 这类可能触发 reallocate 的操作,之前拿到的迭代器就废了。


















