std::binary_search要求容器已排序且使用匹配比较函数,仅返回存在性布尔值;传入乱序容器或不一致比较器将导致未定义行为,时间复杂度O(log N)。

std::binary_search 用对的前提:容器必须已排序
它不负责排序,只做存在性判断。如果传入乱序容器,结果未定义——可能返回 false 即使元素存在,也可能偶然返回 true。常见错误是直接对 std::vector 调用,却忘了先调用 std::sort。
- 升序容器(默认):用
std::less比较,要求() 可用且满足严格弱序 - 降序或自定义顺序:必须传入相同比较函数,否则行为错误
- 迭代器范围必须合法:
first可达last,且[first, last)是有效区间
基本用法与参数细节
函数签名是 std::binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp = Compare{})。注意它只接受前向迭代器及以上(std::list 不行),且不返回位置,只返回 bool。
-
value类型必须能被comp接受:比如用std::greater查找时,() value仍为int,但比较逻辑是“大于” - 若用自定义比较函数,务必确保它和排序时用的一致,否则结果不可靠
- 时间复杂度是
O(log N),但常数比手写二分略高(因泛型实现有额外分支)
std::vectorv = {1, 3, 5, 7, 9}; std::sort(v.begin(), v.end()); // 必须先排 bool found = std::binary_search(v.begin(), v.end(), 5); // true bool missing = std::binary_search(v.begin(), v.end(), 4); // false
和 lower_bound / upper_bound 的关键区别
很多人想“查是否存在”,却误用 std::lower_bound 后判断是否等于 end()。这可行,但多做了事:它实际定位了插入点,而 std::binary_search 内部可早停(找到即返 true)。
-
std::binary_search:仅布尔结果,语义清晰,开销最小 -
std::lower_bound:返回第一个 ≥ value 的迭代器,适合需要位置的场景 - 若需知道重复元素个数,得组合
std::lower_bound和std::upper_bound - 三者都要求相同排序前提,混用不同比较函数会导致逻辑断裂
容易忽略的陷阱
最隐蔽的问题是自定义类型 + 自定义比较器时,value 参数类型和比较器参数类型不匹配。例如比较器接受 const MyStruct&,但传入的是 int 字面量,编译可能通过(隐式转换),运行时逻辑错乱。
立即学习“C++免费学习笔记(深入)”;
- 用
auto推导迭代器类型时,确保不是const_iterator与非const容器混用(虽通常不影响查找,但易引发后续修改误操作) -
std::binary_search对std::set或std::map是冗余的:它们自带find()成员函数,平均复杂度同为O(log N),且更直观 - 调试时若结果不符预期,优先检查排序是否执行、比较器是否一致、迭代器范围是否越界
它只回答“有没有”,不关心“在哪儿”或“有几个”。把问题想清楚再选接口,比硬套模板更重要。










