最省事的是用 std::find,但需注意它返回迭代器而非下标;找不到时返回尾后迭代器,应与 end() 比较判断,再用 std::distance 计算下标。

用 std::find 最省事,但得注意返回值不是下标
直接调用 std::find 是 C++ 里最常用、也最不容易出错的方式。它返回的是迭代器,不是整数下标——这点很多人第一次用就踩坑,比如写成 int pos = std::find(...) 编译不过,或者误以为返回 0 表示没找到。
正确做法是:先和 end() 比较判断是否找到,再用 std::distance 算下标:
int arr[] = {10, 20, 30, 40, 30};
int n = 5;
auto it = std::find(arr, arr + n, 30);
if (it != arr + n) {
int idx = std::distance(arr, it); // idx == 2,不是 0 或 -1
}
-
std::find要求随机访问迭代器,原生数组、std::vector、std::array都行;std::list也能用,但性能差(O(n) 且没法跳转) - 找不到时返回尾后迭代器(如
arr + n),绝不是nullptr或-1 - 如果只关心“是否存在”,不用下标,直接判
it != end就够了,省掉distance开销
手写循环查下标更直观,适合简单场景
当数组小、逻辑简单、或不想引入 <algorithm></algorithm> 头文件时,裸循环反而更清晰,也更容易控制行为(比如找最后一个匹配项、跳过某些条件)。
注意边界检查别越界,尤其用 size_t 当索引时容易和负数比较出问题:
int arr[] = {5, 8, 2, 8, 9};
int n = 5;
int target = 8;
int idx = -1;
for (int i = 0; i
- 用
int做索引比size_t更安全,避免i >= 0这种恒真判断 - 初始化
idx = -1是惯例,表示“未找到”;返回前务必检查是否仍为 -1 - 如果数组是升序的,且要查多次,提前建索引或改用
std::lower_bound更快
查不到时返回什么?统一用 -1 还是抛异常?
没有标准答案,取决于你的接口契约。C++ 标准库选择返回尾后迭代器,不抛异常、也不硬编码 -1——因为容器类型不同,-1 对 size_t 是极大值,会出大问题。
- 如果你的函数声明返回
int,返回 -1 合理,调用方也习惯 - 如果返回
size_t或std::vector<t>::size_type</t>,绝不能返回 -1(会变成 18446744073709551615) - 想强制调用方处理“未找到”情况?考虑返回
std::optional<size_t></size_t>(C++17 起),比 bool + 输出参数干净 - 别为了“看起来优雅”在查不到时抛
std::runtime_error——查找失败不是异常,是正常流程分支
性能敏感时:确认是否真需要“查找”,还是能换结构
如果频繁按值查位置,数组本身可能就不是最优存储结构。每次 std::find 都是 O(n),累积起来很伤。
- 值唯一且静态?建个
std::unordered_map<value_type size_t></value_type>,查 O(1),空间换时间 - 值有重复?用
std::unordered_multimap,或std::map<value_type std::vector>></value_type> - 数组有序且只读?二分查找(
std::lower_bound)降到 O(log n),但注意它返回迭代器,同样要转下标 - 如果是嵌入式或栈上小数组(≤ 16 元素),编译器常把循环自动向量化,
std::find和手写差别不大
真正容易被忽略的是:别默认“必须用数组”。很多所谓“快速查找位置”的需求,本质是数据组织方式没对齐访问模式。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











