std::string::find 判断子串是否存在最直接这是 C++ 标准库中最常用、最轻量的方式。它返回子串首次出现的索引,没找到时返回 std::string::npos。
注意:不要用 == -1 判断失败——std::string::npos 是无符号类型(通常是 size_t),值为 static_cast,直接和 -1 比较会触发隐式转换警告或逻辑错误。
std::string s = "hello world";
std::string sub = "world";
if (s.find(sub) != std::string::npos) {
// 找到了
}
std::string_view::find
如果原始字符串是只读的、生命周期可控(比如来自函数参数或常量字符串字面量),用 std::s 替代
tring_viewstd::string 能避免拷贝开销,find 行为一致但更快。
std::string_view sv = "The quick brown fox";
if (sv.find("fox") != std::string_view::npos) {
// 成功
}
std::string_view 不拥有数据,构造零成本std::string
std::regex
当需求超出“是否包含”——比如要找全部出现位置、提取捕获组、支持 .* 或字符类——std::regex 是标准方案,但代价明显更高。
std::string text = "a1b2c3";
std::regex pattern(R"(\d)");
auto begin = std::sregex_iterator(text.begin(), text.end(), pattern);
auto end = std::sregex_iterator();
for (auto it = begin; it != end; ++it) {
std::cout << it->str() << "\n"; // 输出 1, 2, 3
}
std::regex 对象std::regex 的实现质量差异大(尤其 GCC libstdc++ 历史上有 bug 和性能问题)标准库没有内置 case-insensitive find,常见做法是转小写后查,但直接用 std::tolower 处理多字节字符(如 UTF-8 中文、德语 ß)会出错——它只对单字节 char 安全。
std::tolower 遍历转换std::ranges::search + 自定义谓词boost::algorithm::icontains,它内部处理了 locale 边界真正容易被忽略的是:哪怕只是判断“是否包含”,在跨平台或国际化场景下,std::string::find 的语义仍是字节级精确匹配——它不理解 Unicode 码点、组合字符或正规化形式。这时候“包含”本身就需要重新定义。