推荐用 std::find 获取下标:先用 std::find 找到迭代器,再减去起始迭代器得下标;对 vector 可用 std::distance,语义更明确且兼容所有容器,但需先判断是否找到。

用 std::find 获取元素下标(推荐)
直接用 std::find 找到迭代器,再减去数组起始地址,就是下标。它适用于所有标准容器和原生数组,且语义清晰、不易越界。
注意:如果没找到,返回的是尾后迭代器,此时计算下标会得到非法值,必须先判断。
int arr[] = {10, 20, 30, 40, 50};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 30;
auto it = std::find(std::begin(arr), std::end(arr), target);
if (it != std::end(arr)) {
int index = it - std::begin(arr); // 下标是整数差,不是指针减法的字节数
std::cout << "found at index: " << index << "\n"; // 输出 2
} else {
std::cout << "not found\n";
}
对 std::vector 用 std::distance
当数组封装在 std::vector 中时,std::distance 更通用,尤其适合非随机访问迭代器(虽然 vector 是随机访问,但写法更一致)。
-
std::distance内部对随机访问迭代器做减法,和直接相减等价,但语义更明确 - 对
list或forward_list也能用(只是性能为 O(n)) - 不要对空容器调用
std::distance(begin, end)以外的组合,可能未定义行为
std::vectorvec = {10, 20, 30, 40}; auto it = std::find(vec.begin(), vec.end(), 30); if (it != vec.end()) { auto index = std::distance(vec.begin(), it); // 返回 size_t 类型 std::cout << "index: " << index << "\n"; // 输出 2 }
手写循环时避免常见越界错误
手动遍历看似简单,但容易写出 i 或漏判 size == 0 等错误。C++ 中数组下标是 [0, size) 半开区间,这点必须严格遵守。
立即学习“C++免费学习笔记(深入)”;
- 用
size_t作索引变量时,i--在 0 时会绕成极大值,导致无限循环或崩溃 - 比较时别混用有符号/无符号:比如
int i和vec.size()(返回size_t)比较可能触发隐式转换警告或逻辑错误 - 优先用基于范围的 for 循环 + 计数器,比裸指针更安全
int arr[] = {5, 15, 25};
size_t n = std::size(arr); // C++17 起推荐,比 sizeof 安全
size_t index = n; // 初始化为无效值
for (size_t i = 0; i < n; ++i) {
if (arr[i] == 15) {
index = i;
break;
}
}
if (index != n) {
std::cout << "found at " << index << "\n";
}查找失败时的返回值处理(关键细节)
几乎所有查找函数都用“尾后位置”表示未找到,但不同接口返回类型不同,容易误用:
-
std::find返回迭代器 → 必须和end()比较,不能和nullptr或-1比 -
std::search、std::find_if同理 - 自定义函数若返回
int,应明确约定:-1 表示未找到;但要注意和合法下标(如unsigned容器)冲突 - 对
std::array或std::span,同样适用std::find+ 迭代器差值,无需特殊处理
真正麻烦的不是怎么找,而是后续代码是否统一按“迭代器有效性”来分支——一旦混用 -1 和迭代器判断,很快就会出现静默错误。











