upper_bound查找第一个严格大于目标值的元素位置,要求区间已排序,返回迭代器,若无满足元素则返回末尾迭代器;使用时需区分lower_bound,注意自定义比较函数的语义一致性,并通过it != container.end()判断是否找到。

upper_bound 查找第一个大于目标值的元素位置
upper_bound 是 STL 中用于在**已排序区间**中查找第一个严格大于给定值的元素的函数。它不找“等于”,也不找“大于等于”,只认准“严格大于”。返回的是一个迭代器,指向该元素;如果所有元素都不满足条件,就返回末尾迭代器(如 v.end())。
常见错误是把它和 lower_bound 混用:比如想查“大于等于”,却用了 upper_bound,结果跳过相等元素直接往后找,导致逻辑偏移。
使用前必须确保容器/数组已升序排列,否则行为未定义——哪怕只错一个位置,upper_bound 也可能返回完全错误的迭代器。
vector 和普通数组上怎么调用 upper_bound
对 std::vector,直接传入 begin()、end() 和目标值:
立即学习“C++免费学习笔记(深入)”;
std::vectorv = {1, 2, 2, 3, 4, 4, 5}; auto it = std::upper_bound(v.begin(), v.end(), 2); // 指向第1个3,即索引3
对原始数组,需手动传入指针:
int arr[] = {1, 2, 2, 3, 4, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
auto ptr = std::upper_bound(arr, arr + n, 4); // 指向5,即 arr + 6
- 第三个参数是值本身,不是引用或指针
- 返回类型始终是输入迭代器类型(
vector::iterator或int*),别用auto后误当成int - 若要转成下标,用
it - v.begin(),不是std::distance(v.begin(), it)——虽然后者也对,但前者更高效且直观
自定义比较函数时 upper_bound 的写法
当容器按降序排列,或元素类型没有默认 ,就得传自定义比较函数。关键点是:比较函数语义必须和排序方式一致。
例如降序排列的 vector:
std::vectorv = {5, 4, 4, 3, 2, 2, 1}; // 降序 auto it = std::upper_bound(v.begin(), v.end(), 3, std::greater ()); // 找第一个 < 3 的位置?不对!
注意:upper_bound 内部仍按“升序逻辑”理解比较函数。传 std::greater,意味着它把“a > b”当作“a 在 b 前面”,所以整个逻辑翻转了。此时 upper_bound(..., 3, greater 实际找的是第一个 **小于等于 3** 的位置(因为“大于”在降序里对应“靠前”,而 upper_bound 要找“第一个不满足 comp(value, element)”的位置)。
更安全的做法是统一用升序 + 自定义谓词,或改用 std::lower_bound 配合反向逻辑。复杂场景建议先手写二分验证边界行为。
upper_bound 返回值为空或越界时怎么判断
upper_bound 永远不会崩溃,但可能返回 v.end()。这是合法且常见的,比如目标值比所有元素都大,或容器为空:
std::vectorv; auto it = std::upper_bound(v.begin(), v.end(), 10); if (it == v.end()) { // 没找到,v 为空或所有元素 ≤ 10 }
- 永远不要对
v.end()解引用(*it会未定义行为) - 不要用
it == v.begin()判断“没找到”——它可能恰好指向首元素(比如所有元素都大于目标值) - 若需知道是否存在大于目标值的元素,只比较
it != v.end()即可
真正容易被忽略的是:当目标值本身不存在于序列中,upper_bound 和 lower_bound 可能返回同一位置。这时候仅靠返回值无法区分“等于不存在”还是“大于不存在”,得结合上下文或额外检查。










