std::string::find循环查找需设起始位置为pos+1(重叠)或pos+sub.length()(非重叠),避免溢出和空串未定义行为,推荐用std::vector存索引并结合std::string_view提升性能。

用 std::string::find 循环查找最直接
标准库的 find 函数返回子串首次出现的索引,找不到时返回 std::string::npos。关键是要在每次找到后,从下一个位置继续搜索,而不是从头开始——否则会无限循环或漏匹配。
- 起始搜索位置必须设为
pos + 1(单字符偏移)或pos + sub.length()(跳过已匹配部分),取决于是否允许重叠匹配 - 如果子串为空(
sub.empty()),find行为未定义,务必提前检查 - 注意
size_t是无符号类型,pos - 1可能溢出成极大值,不要写pos = find(...) + 1这类表达式
重叠匹配 vs 非重叠匹配要明确选择
比如在字符串 "aaaa" 中找 "aa":重叠匹配返回位置 0,1,2;非重叠则只返回 0,2。C++ 标准库不内置重叠判断,得靠手动控制搜索起点。
- 非重叠:每次找到后,设置
pos = found + sub.length() - 重叠:每次设置
pos = found + 1 - 若子串长度为 0,两种逻辑都应拒绝执行,避免死循环
用 std::vector<size_t></size_t> 存位置比计数更实用
单纯统计次数容易掩盖需求本质——多数场景真正需要的是所有位置用于后续处理(如替换、高亮、切片)。边找边存索引,比先计数再遍历更高效也更灵活。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 声明容器:
std::vector<size_t> positions;</size_t> - 循环内:找到就
positions.push_back(found); - 最后
positions.size()就是总次数,positions本身可直接用于迭代 - 避免用
int存索引——长字符串下size_t更安全
注意 std::string_view 在 C++17+ 中可避免拷贝
如果原始字符串很大且只读,用 std::string_view 替代 std::string 参数能省掉构造开销,尤其适合高频调用或嵌入式环境。
立即学习“C++免费学习笔记(深入)”;
- 函数签名建议写成:
std::vector<size_t> findAll(std::string_view str, std::string_view sub)</size_t> -
string_view::find接口与string::find完全一致,无需改逻辑 - 但要注意:传入的
str生命周期必须长于函数调用,否则string_view会悬空
实际用的时候,别光盯着“统计个数”,先想清楚要不要位置、允不允许重叠、源字符串会不会很大——这些决定怎么写循环和选什么类型。

















