c++oding="utf-8" ?>
应使用 size_t pos = 0 初始化,循环调用 find 并令 pos = pos + 1 以支持重叠匹配(如 "aaaa" 中找 "aa" 得 0,1,2),避免 pos + sub.length() 跳过重叠;须检查 npos、禁止空子串、防止无符号溢出。

用 std::string::find 循环查找所有匹配位置
直接调用一次 find 只能拿到第一个匹配索引,必须手动控制搜索起始位置才能找出全部。关键点在于每次找到后,把下一次搜索起点设为 pos + 1(不是 pos + 子串长度),否则会漏掉重叠匹配(比如在 "aaaa" 中找 "aa",正确结果是 0,1,2)。
常见错误是写成 pos = s.find(sub, pos + sub.length()),这会跳过重叠情况;还有人忘记初始化 pos = 0 或没检查 find 返回的 std::string::npos 就直接用,导致无限循环或越界。
实操建议:
- 用
size_t pos = 0初始化,循环条件为pos != std::string::npos - 每次循环内先调用
find,再把结果存入 vector,最后更新pos = pos + 1 - 如果确定不需要重叠匹配,才用
pos + sub.length(),但得确保sub非空,否则sub.length() == 0会导致死循环
用 std::search 配合迭代器更灵活
std::search 是泛型算法,不依赖 std::string,可作用于任意容器(如 std::vector<char></char> 或 C 风格数组),返回的是迭代器而非索引,需要减去 begin() 才能得到下标。
它默认行为和 find 一样——不重叠;若要重叠匹配,得自己移动迭代器:找到后令 it = it + 1,而不是 it = it + sub.size()。
优势在于可自定义比较逻辑(传入二元谓词),比如忽略大小写或按 ASCII 值模糊匹配;劣势是代码略长,且对初学者来说迭代器运算容易出错(比如对 end() 迭代器做 +1 会未定义)。
实操建议:
- 查完立即检查是否等于
haystack.end(),别直接解引用 - 计算索引时统一用
std::distance(haystack.begin(), it),比手动减更安全 - 若子串为空,
std::search行为由标准规定:返回haystack.begin(),需单独判断避免意外
性能与边界情况必须提前处理
子串为空(sub.empty() == true)时,find 和 search 都会返回 0 或开头迭代器,但语义上“空串出现在每个位置”,实际业务中通常应直接拒绝或特殊处理,否则结果数组会包含从 0 到 s.length() 的所有整数,极易 OOM。
另一个坑是 std::string::find 参数类型是 size_t,如果用负数偏移(比如误写 pos - 1)会因无符号溢出变成极大值,导致循环卡死。
实操建议:
- 函数入口加
if (sub.empty()) throw std::invalid_argument("empty substring not allowed"); - 所有涉及
pos更新的地方,用if (pos == std::string::npos) break;而不是依赖循环条件 - 调试时打印每次
find的返回值,确认是否真为npos,有些编译器在优化下可能隐藏问题
要不要用 std::regex_iterator?
可以,但绝大多数场景没必要。正则引擎开销大,启动慢,且 std::regex 在 MSVC 和 libstdc++ 上实现质量差异明显——GCC 11 之前甚至不支持 regex_iterator 的部分构造方式。单纯找固定子串,它比 find 慢 5–10 倍。
唯一适合的情况是:子串本身带通配(如 "a.c")、需要捕获分组、或后续要复用同一模式多次匹配。此时注意 std::regex_constants::match_default 默认不重叠,要重叠得手动控制 std::sregex_iterator 的起始位置。
实操建议:
- 只在明确需要正则能力时引入,别为“看起来高级”而用
- 若必须用,优先缓存
std::regex对象,避免重复编译 - 测试时务必覆盖空字符串、超长字符串(>1MB)、含 null 字符的 string,regex 容易在这里崩
重叠匹配逻辑和空子串处理,是几乎所有实现里最容易被跳过的两处。哪怕只是内部工具函数,也建议加断言或日志,不然线上跑着跑着突然内存爆了,还得倒回去翻哪行漏了判断。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











