std::equal_range是严格要求容器已排序且支持随机访问的标准库函数,返回匹配值的左右边界迭代器对,使用时必须确保比较函数与排序一致。

std::equal_range 不是“二分查找边界技巧”,它是标准库里一个**严格按规则做事的工具函数**——用对了省事,用错了连编译都过不去,更别说查到想要的边界。
std::equal_range 要求容器必须已排序且支持随机访问
它底层调用 lower_bound 和 upper_bound,两者都依赖 operator< 逐段比较。如果容器没排好序,返回的迭代器指向完全不可预测的位置;如果是 std::list 或 std::forward_list 这类不支持随机访问的容器,直接编译失败(因为内部用了 std::advance + 算术运算)。
- ✅ 正确:用在
std::vector<int>、std::array<double, N>上,且已调用std::sort - ❌ 错误:对未排序的
std::vector直接调用,结果无意义 - ❌ 错误:传入
std::list<int>,编译报错:no match for 'operator+' in '__middle + __len'
返回值是 pair<iterator, iterator>,别漏解包
它不返回下标,也不返回 bool,而是一个 std::pair,.first 是左边界(首个 ≥ target 的位置),.second 是右边界(首个 > target 的位置)。常见错误是当成单个迭代器用,或者忘记检查是否为空。
- 用
auto [l, r] = std::equal_range(v.begin(), v.end(), x);解包最安全(C++17 起) - 如果想判断 target 是否存在:检查
l != r,而不是l != v.end() - 获取匹配元素个数:用
std::distance(l, r),不是r - l(虽然后者在 vector 里也行,但不通用)
自定义比较函数必须和排序时一致
如果你用 std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); 降序排,那 std::equal_range 也必须传同样的 lambda,否则行为未定义——它不会“猜”你当初怎么排的。
立即学习“C++免费学习笔记(深入)”;
- 升序排序 → 用默认比较(或
std::less<>{}) - 降序排序 → 必须显式传
std::greater<>{},不能省略 - 结构体排序:比较函数签名必须和
sort中完全一致,包括 const 与引用限定 - 错误示例:
std::equal_range(v.begin(), v.end(), obj, [](const auto& a, const auto& b) { return a.id < b.id; }),但排序时用的是[](auto a, auto b) { return a.id < b.id; }(少了 const&)→ 可能编译失败或运行时越界
最容易被忽略的是:它只认“严格弱序”,不处理 NaN、指针比较、自定义类型中 operator< 不满足传递性等情况。一旦比较逻辑有歧义,equal_range 返回的结果就不可靠——这不是函数的问题,是你数据契约没守好。








