最直接的做法是用 std::find 配合 begin()/end(),返回迭代器而非值;类型须严格匹配;std::any_of 更适合带条件的查找;手写循环需注意 int 与 size_t 混用及 const 引用。

用 std::find 最直接,但得注意迭代器失效和类型匹配
标准做法是用 std::find 配合容器的 begin() 和 end()。它返回第一个匹配元素的迭代器,没找到就返回 end()。别直接比较值——比如写 if (std::find(...) == 5) 是错的,因为返回的是迭代器,不是值。
常见错误现象:std::find(arr, arr + size, val) 用在 C 风格数组时,arr + size 超出边界却没报错,但行为未定义;换成 std::array 或 std::vector 更安全。
- 对
std::vector<int>:用std::find(v.begin(), v.end(), x) != v.end() - 对 C 风格数组:确保
size准确,且数组非空(空数组时arr + 0合法,但std::find返回arr,比较需谨慎) - 类型必须严格匹配:查找
int时传long可能因隐式转换失败,尤其自定义类型要重载operator==
用 std::any_of 更语义化,适合带条件的查找
如果判断逻辑不止是“等于”,比如“是否大于 10”或“是否为偶数”,std::any_of 比 std::find 更自然。它接受一个一元谓词,返回 bool,语义清晰,不用处理迭代器。
性能上两者都是 O(n),但 std::any_of 在 lambda 中写条件更直观,也避免了迭代器解引用出错(比如误写 *it == nullptr)。
立即学习“C++免费学习笔记(深入)”;
- 基础用法:
std::any_of(v.begin(), v.end(), [x](int a) { return a == x; }) - 支持移动捕获:
[&x]或[x]都行,但注意 lambda 生命周期不能长于容器 - 对
std::array同样适用,且编译期知道大小,部分优化器可能做更好内联
手写循环最可控,但别忽略 const 和无符号整数陷阱
简单场景下,裸 for 循环反而最易读、调试方便,也最容易加日志或断点。但两个坑高频出现:一是遍历时用 int i 遍历 size_t 大小的容器,导致 i >= 0 永真;二是忘记加 const 引用,引发不必要的拷贝(尤其对象较大时)。
错误示例:for (int i = 0; i —— 当 <code>v.size() == 0 时 v.size() 是 size_t,i 比较会把 <code>i 转成无符号,i 为负时变成极大正数,循环不执行或崩溃。
- 推荐写法:
for (const auto& elem : v) if (elem == x) return true;(范围 for,自动处理类型) - 索引安全写法:
for (size_t i = 0; i ,或用有符号类型时先转:<code>auto n = static_cast<ptrdiff_t>(v.size()) - 若需索引且容器可能为空,务必检查
v.empty()再进循环
std::binary_search 快但前提苛刻:必须已排序且支持随机访问
如果数组已排序且你追求 O(log n),std::binary_search 是唯一选择。但它不返回位置,只返回 bool;而且要求容器支持随机访问迭代器(std::vector、std::array、C 风格数组可以,std::list 不行),还必须严格升序(或按同一 Compare 规则排序)。
容易被忽略的点:排序和查找用的比较逻辑必须一致。比如用 std::greater<int>() 排序,就得传同样的 Compare 给 std::binary_search,否则结果不可靠。
- 基本调用:
std::binary_search(v.begin(), v.end(), x) - 自定义排序后查找:
std::binary_search(v.begin(), v.end(), x, std::greater<int>{}) - 未排序数组上调用,行为未定义——不会报错,但返回值完全不可信
std::find 或范围 for 就够了。std::binary_search 看似快,但排序本身是 O(n log n),除非反复查且数组长期不变,否则得不偿失。最常被漏掉的其实是 const 正确性和无符号整数比较——这两个问题在线上环境才容易暴露,本地测试常侥幸通过。


















