string::starts_with 在 C++20 中才引入,旧编译器需用 str.compare(0, prefix.length(), prefix) == 0 替代,并注意长度检查与 string_view 生命周期安全。

string::starts_with 在 C++20 中才可用
如果你的编译器不支持 C++20,直接调用 str.starts_with("prefix") 会报错:「no member named 'starts_with'」。这不是写错了,是标准版本不够。GCC 10、Clang 12、MSVC 19.30+ 才开始支持,且需显式开启 -std=c++20(或 /std:c++20)。
常见误判场景:用较老的 IDE(如旧版 VS Code + 默认 MinGW)、CI 环境未更新 C++ 标准、或者误以为头文件包含就能用——其实它属于 std::string 的原生成员函数,不依赖额外头文件,但强依赖语言标准。
替代方案:substr + compare 最兼容
在 C++11 及以后都稳稳可用,原理简单:取子串再比对。关键是边界处理不能漏,否则 substr 抛 std::out_of_range。
- 先检查原字符串长度是否 ≥ 前缀长度,否则直接返回
false - 用
str.substr(0, prefix.length()) == prefix最直观,但有临时对象开销 - 更高效写法是
str.compare(0, prefix.length(), prefix) == 0,零拷贝、复用已有缓冲区
示例:
bool starts_with(const std::string& str, const std::string& prefix) {
if (prefix.length() > str.length()) return false;
return str.compare(0, prefix.length(), prefix) == 0;
}
注意 string_view 版本的陷阱
如果前缀是字面量(如 "http"),用 std::string_view 替代 std::string 传参能避免隐式构造,但要注意生命周期——string_view 不拥有数据,若传入的是局部 char[] 或临时 std::string 的 c_str(),可能悬空。
立即学习“C++免费学习笔记(深入)”;
安全写法:
- 前缀为字面量时,直接用
std::string_view{"abc"}(字面量生命周期是静态的) - 避免
string_view{some_string.c_str()},改用string_view{some_string} - 若函数参数是
string_view,调用方必须确保被视图引用的内存在函数执行期间有效
性能差异其实很小,别过早优化
对短字符串(compare、substr + ==、C++20 starts_with 三者实测耗时差距在纳秒级。真正影响性能的是反复构造 std::string 前缀(比如循环里写 starts_with("log_" + level)),这会产生不必要的堆分配。
更合理的做法:
- 把固定前缀声明为
static constexpr std::string_view - 用
std::string_view::starts_with(C++17 起就有,且无需 C++20) - 例如:
static constexpr std::string_view kLogPrefix = "log_"; … str_sv.starts_with(kLogPrefix);
C++17 的 string_view::starts_with 是真正轻量、无分配、跨平台就绪的选项,比折腾 substr 更干净,也比等 C++20 更现实。


















