std::ranges::equal_range不能直接用在未排序vector上,因它要求输入为std::ranges::sorted_range,否则行为未定义;它返回subrange,需结构化绑定解包,且仅支持random_access_range如vector、array。

std::ranges::equal_range 为什么不能直接用在 vector 上?
它要求范围必须已排序,否则行为未定义——不是报错,而是返回看似合理但完全错误的迭代器。比如对乱序 std::vector 调用 std::ranges::equal_range,可能返回一对指向中间位置的迭代器,而你根本找不到目标值。
- 必须先确保容器已升序排列(或按自定义比较器排序),
std::sort或构造时有序是前提 - 若用自定义比较器(如
std::greater<int></int>),所有后续操作(包括equal_range)必须传入同一比较器,否则结果不可靠 -
std::ranges::equal_range返回的是std::ranges::subrange(C++20),不是传统std::pair<it it></it>;解包时用结构化绑定更安全:auto [first, last] = std::ranges::equal_range(v, x);
如何正确调用 std::ranges::equal_range 查找重复元素区间
它本质是 std::lower_bound + std::upper_bound 的组合封装,返回所有等于给定值的连续元素范围(左闭右开)。适用于去重统计、批量删除、区间高亮等场景。
- 输入范围必须是
std::ranges::random_access_range(如std::vector、std::array、原生数组),否则编译失败 - 查找值类型需能隐式转换为范围元素类型,或显式提供
proj投影(如查找std::vector<person></person>中 age == 30 的人:equal_range(v, 30, {}, &Person::age)) - 示例:
std::vector<int> v = {1, 2, 2, 2, 3, 4, 4};<br>auto [first, last] = std::ranges::equal_range(v, 2);<br>// first 指向索引1,last 指向索引4 → 共3个2</int>
std::ranges::equal_range 和 std::equal_range 有什么实际区别?
前者是 C++20 范围库版本,后者是传统迭代器版;两者语义一致,但接口和约束不同。
-
std::equal_range接收两个迭代器(begin,end)+ 值,std::ranges::equal_range直接接收范围对象(如v)+ 值,更简洁且支持管道操作(v | std::views::filter(...) | std::ranges::equal_range(x)) -
std::ranges::equal_range对 range 概念做静态检查,编译期就能捕获不满足std::ranges::sorted_range的误用(比如传入std::list);而传统版只在运行时表现出错行为 - 性能无差异,底层都走二分搜索,复杂度都是 O(log n)
常见编译错误:'no matching function for call to equal_range'
多数是因为范围未满足 std::ranges::range 概念,或缺少必要头文件与命名空间。
- 确认包含
<algorithm></algorithm>和<ranges></ranges>(C++20 必须) - 避免对
std::initializer_list直接调用(它不是std::ranges::random_access_range),改用std::vector包装后再查 - 若使用自定义类型,确保重载了
operator 或提供严格弱序比较器,并通过 <code>std::ranges::less{}显式传递 - Clang/GCC 需开启
-std=c++20,MSVC 需 VS 2019 16.10+ 且启用/std:c++20
equal_range 就不会报错,只会默默返回垃圾结果——得靠单元测试覆盖边界 case 才能暴露问题。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











