std::equal_range适用于已排序的容器如vector、array、deque的有序段及set、map等关联容器,用于查找目标值在有序序列中的起始与结束位置(含重复),返回[first, second)区间;不支持unordered_set等无序容器,且要求输入真实有序、比较器一致。

std::equal_range 适用于哪些容器和场景
std::equal_range 只能用于**已排序的范围**,比如 std::vector、std::array 或 std::deque 的有序片段,也适用于 std::set、std::map 等底层有序的关联容器(此时键天然有序)。它不接受无序容器如 std::unordered_set,也不检查输入是否真有序——若传入乱序数据,结果未定义。
典型使用场景是:你想知道某个值在有序序列中“从哪开始、到哪结束”(含重复元素),比如统计频次、批量修改相同键的映射项、或为插入预留连续空位。
调用方式与返回值含义必须对齐
std::equal_range 返回 std::pair<it it></it>,其中 first 是第一个 ≥ 目标值的迭代器,second 是第一个 > 目标值的迭代器。也就是说,[first, second) 是所有等于目标值的元素构成的左闭右开区间。
- 若目标不存在,
first == second,区间为空 - 若容器用自定义比较器(如
std::greater<int></int>),必须保证equal_range调用时传入**同一个比较器**,否则行为错误 - 对
std::map,应传入map.begin()和map.end(),而非map.keys()(C++20 才有 keys view,且不保证可随机访问)
示例:
std::vector<int> v = {1, 2, 2, 2, 3, 4, 4};
auto range = std::equal_range(v.begin(), v.end(), 2); // [v.begin()+1, v.begin()+4)
// range.first 指向第一个 2,range.second 指向 3</int>
和 lower_bound / upper_bound 的关系别搞混
std::equal_range 功能上等价于同时调用 std::lower_bound 和 std::upper_bound,但**不是简单拼接两次二分**:标准库实现通常只做一次二分查找,内部复用比较逻辑,性能略优(尤其对代价高的比较操作)。
- 别写成
{lower_bound(...), upper_bound(...)}—— 多一次遍历,且可能因中间被修改导致结果不一致 - 若只需判断存在性,用
binary_search更清晰;若只关心起始位置,用lower_bound即可 - 注意:所有这三个函数都要求严格弱序(strict weak ordering),不能用
替代 <code> 作比较器
常见错误:迭代器失效与 const 正确性
对 std::vector 等序列容器,equal_range 返回的迭代器在容器发生 push_back、resize 或 erase 后立即失效。若你拿到 range 后打算批量 erase,必须先保存位置或用 erase-remove 惯用法。
- 对
const容器,必须用const_iterator调用,否则编译失败(例如v.cbegin()/v.cend()) - 若容器元素是自定义类型,确保比较器能处理
const T&参数,尤其当重载了operator 但没加 <code>const限定符时 - 在
std::map<k></k>中查 key 时,传的是K类型值,不是std::pair<k></k>—— 否则编译报错或匹配失败
真正容易被忽略的是:equal_range 不保证容器线程安全。多线程读+写同一容器时,哪怕只读取 range,也需外部同步——因为底层实现可能依赖容器状态缓存或分支预测优化。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











