最直接的方式是用 std::search,它返回首个匹配的起始迭代器,需手动转为下标,未找到时返回结束迭代器;不可误用 std::find_first_of,因其查找单个匹配元素而非连续子序列。

用 std::search 找子数组首次出现位置
最直接的方式是用标准库的 std::search,它专为这种「在序列中查找子序列」设计,支持任意迭代器类型,且对原始数组、std::vector、std::array 都适用。
注意:它返回的是首个匹配的起始迭代器,不是下标索引,需要手动计算偏移;如果没找到,返回的是结束迭代器(如 end()),必须检查再解引用。
-
std::search默认用operator==比较,适用于 POD 类型和重载了==的类 - 若需自定义比较逻辑(比如忽略大小写、浮点近似相等),可传入第 4 个参数——一个二元谓词函数对象
- 时间复杂度最坏 O(n×m),n 是父数组长度,m 是子数组长度;不适用于高频、超长数组的实时查找
int arr[] = {1,2,3,4,2,3,5};
int sub[] = {2,3};
auto it = std::search(std::begin(arr), std::end(arr),
std::begin(sub), std::end(sub));
if (it != std::end(arr)) {
size_t pos = it - std::begin(arr); // 转为下标
// pos == 1
}
用 std::find_first_of 不行,别误用
std::find_first_of 常被误当成子数组查找工具,但它语义完全不同:它是在父序列中找「任意一个」属于子序列的元素,不是找连续子序列。用它查 {2,3} 在 {1,2,3,4} 中的位置,会直接返回第一个 2 的位置,完全忽略后续是否连成 2,3。
- 错误现象:输入
{1,3,2,3}查{2,3},std::find_first_of返回索引 2(即2的位置),但实际{2,3}出现在索引 2–3,而你无法仅靠这个结果确认是否完整匹配 - 它适合「找任意一个候选元素」场景,比如从字符集中找第一个出现的分隔符,不适合子数组匹配
手写朴素匹配时,边界检查最容易漏
自己写循环匹配虽简单,但下标越界是高频 bug。关键在于:外层循环不能遍历到父数组末尾,而要留出子数组长度的空间。
- 错误写法:
for (int i = 0; i → 当 <code>i == n-1且子数组长度 >1 时,访问arr[i+1]就越界 - 正确上限:
i (n 父长,m 子长),用 <code> 或 <code> 都行,但必须减去 <code>m - 若用无符号类型(如
size_t),n - m在n 时会整数溢出变成极大值,导致无限循环——务必先判断 <code>n 直接返回失败
字符串场景优先用 std::string::find
如果操作对象是 std::string(哪怕内容是数字字符),别绕路转成 int 数组再搜。C++ 字符串的 find 方法底层优化充分,且接口更安全:
-
str.find(substr)直接返回size_t下标,找不到时返回std::string::npos - 支持指定搜索起点,适合多次查找;也支持
find_first_of/find_last_of等变体,但注意它们仍不是子串匹配 - 若子串含嵌入空字符(
'\0'),std::string仍能正确处理(因存长度),但 C 风格字符串函数(如strstr)会提前截断
真正难的不是找位置,而是确认你面对的是「数值数组」还是「字节序列」——前者用 std::search,后者用 std::string::find 或 std::search 配合 unsigned char* 迭代器。混淆这两者,90% 的边界问题就源于此。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











