std::lower_bound用于查找插入位置而非值本身,要求容器严格升序,返回第一个不小于给定值的迭代器,未排序时行为未定义。

std::lower_bound 能做二分查找,但不是“找值”,而是“找插入位置”——它返回第一个不小于给定值的迭代器。用错场景或忽略前提条件,结果会完全不对。
必须确保容器已升序排序
这是硬性前提。std::lower_bound 不检查顺序,只按有序假设推进比较。未排序时行为未定义,可能返回任意位置,甚至崩溃。
- 对
std::vector、std::array等,调用前必须手动std::sort(注意:std::sort默认升序) - 对
std::set、std::map,天然有序,可直接用 - 若数据是降序排列,不能直接传
std::greater{}给lower_bound—— 那会破坏语义;应改用std::upper_bound或反向迭代器配合std::lower_bound
理解返回值:它不表示“找到了”,而是“应该插在哪”
即使目标值不存在,std::lower_bound 仍返回有效迭代器(指向第一个 ≥ 值的位置)。是否“找到”,需额外判断:
- 检查
*it == value(仅当it != container.end()时才安全解引用) - 更稳妥写法:
if (it != vec.end() && *it == value) - 若只关心是否存在,且容器支持 O(1) 随机访问(如
vector),用std::binary_search更直观
示例:
立即学习“C++免费学习笔记(深入)”;
std::vector<int> v = {1, 3, 5, 7, 9};
auto it = std::lower_bound(v.begin(), v.end(), 6); // 返回指向 7 的迭代器
// *it 是 7,不是 6 —— 它没“找到”6,只是告诉你可以把 6 插在 7 前面
自定义比较函数要和排序逻辑严格一致
如果用了 std::sort(v.begin(), v.end(), cmp) 排序,那么 std::lower_bound 必须传同一个 cmp,否则位置计算错误。
- 常见错误:排序用
[](int a, int b) { return a > b; }(降序),但lower_bound忘记传该 lambda,仍按默认升序语义查 —— 结果错乱 - 结构体排序时,比较函数必须满足严格弱序(例如不能只比一个字段就返回 true/false,要考虑所有相关字段)
- 避免捕获局部变量的 lambda 在容器生命周期外被调用(比如存为成员变量后反复使用)
性能与迭代器类型限制
std::lower_bound 要求随机访问迭代器才能达到 O(log n)。对 std::list 或 std::forward_list 传其迭代器,实际是线性遍历(O(n)),毫无优势。
- 能用
std::vector就别用std::list做二分查找 -
std::deque支持随机访问,可用,但缓存局部性差,实际性能常不如vector - 若需频繁插入/删除且保持有序,考虑
std::set:它内部是红黑树,find和lower_bound都是 O(log n),且自动维护有序
最容易被忽略的一点:很多人以为 lower_bound 是“查找函数”,于是把它当成 find 的更快替代。但它解决的是不同问题——你真正需要的,有时其实是 std::binary_search 或容器自身的 find 成员函数。


















