std::lower_bound在已排序容器中查找大于等于目标的第一个元素位置,返回迭代器而非下标;若序列未排序、比较函数与排序不一致或未检查it!=end()则行为未定义。

std::lower_bound 查找大于等于目标的第一个位置,前提是容器已排序
它不判断是否排序,只按迭代器范围做二分查找;如果传入未排序序列,结果未定义——常见表现是返回错误的迭代器,甚至越界。必须确保 begin() 到 end() 是升序(或按同一自定义比较规则有序)。
标准用法返回的是迭代器,不是下标,需要减去 begin() 才得索引:
std::vector<int> v = {1, 3, 5, 7, 9};
auto it = std::lower_bound(v.begin(), v.end(), 6);
int pos = it - v.begin(); // pos == 3,对应元素 7自定义比较函数时,必须和排序方式严格一致
比如你用 std::sort(v.begin(), v.end(), std::greater<int>())</int> 降序排列,那 std::lower_bound 就不能直接用默认小于比较,否则逻辑错乱。必须传同样的 std::greater<int>()</int>:
- 升序排列 → 用默认比较(或
std::less<int>()</int>) - 降序排列 → 必须显式传
std::greater<int>()</int> - 自定义结构体 → 比较函数/仿函数/lambda 必须和
sort用的一致,且满足严格弱序
否则可能查到错误位置,或触发断言(Debug 模式下)。
立即学习“C++免费学习笔记(深入)”;
返回值为空指针?不,它返回尾后迭代器,需手动判越界
std::lower_bound 永远不会返回空指针;它在没找到时返回 end()。常见误操作是直接解引用而不检查:
auto it = std::lower_bound(v.begin(), v.end(), 100);
if (it != v.end()) {
std::cout << *it << "\n"; // 安全
} else {
// 元素不存在,或全部小于目标
}容易踩的坑:
- 把
it == v.end()当成“没找到”就完事,其实还要注意:若所有元素都 end() - 对空容器调用,
begin() == end(),此时lower_bound立即返回end(),合法但需提前处理
和 std::upper_bound 的关键区别就一条:等号归属
std::lower_bound 返回第一个 ≥ 目标的迭代器;std::upper_bound 返回第一个 > 目标的迭代器。两者配合可快速统计某值出现次数:
auto l = std::lower_bound(v.begin(), v.end(), x); auto u = std::upper_bound(v.begin(), v.end(), x); int count = u - l;
注意:不要混用比较器——lower_bound 和 upper_bound 必须用完全相同的比较逻辑,否则区间无意义。
边界情况最易忽略:当目标比所有元素都小时,lower_bound 返回 begin();比所有元素都大时,返回 end();等于某个元素时,指向该元素首次出现处——这些行为全部依赖于“已排序”这个前提,缺一不可。


















