删除字符串中固定前缀或后缀最直接用substr,需先检查匹配再截取;删中间片段用find+erase;批量或模式化删除才用regex_replace;仅逻辑跳过可用string_view。

字符串中删除固定前缀或后缀用 substr 最直接
如果“模板片段”是已知的、固定位置(比如开头或结尾)的子串,substr 是最轻量且无副作用的选择。它不修改原字符串,也不涉及查找开销,适合编译期已知长度的场景。
常见错误是硬写索引却忽略边界检查,导致 std::out_of_range 异常。比如想删掉开头的 "prefix_",但没确认字符串真以它开头就直接 s.substr(7)。
- 先用
s.starts_with("prefix_")(C++20)或s.compare(0, 7, "prefix_") == 0(旧标准)判断是否匹配 - 再调用
s.substr(7)获取剩余部分;若不匹配,原样返回或按需报错 - 后缀同理:用
s.ends_with("suffix")或s.compare(s.size() - 6, 6, "suffix") == 0,再s.substr(0, s.size() - 6)
要删中间某段且只删一次,用 find + erase
当模板片段出现在字符串任意位置(比如 JSON 中的占位符 "{{name}}"),且只需删第一次出现时,组合 find 和 erase 是标准解法。注意 erase 会原地修改字符串,且返回的是新长度,不是迭代器。
容易踩的坑是查到 std::string::npos 后仍调用 erase,触发未定义行为。
- 先调用
size_t pos = s.find("{{name}}"); - 检查
if (pos != std::string::npos)再执行s.erase(pos, 8); - 如果模板片段长度不确定(如变量名动态),得先算长度:
s.erase(pos, template_str.length());
多次删除或支持通配,就得上正则 std::regex_replace
std::regex_replace 适合批量替换/删除符合模式的片段,比如删所有 "{{.*?}}" 占位符。但它有明显代价:构造 std::regex 对象开销大,且 C++ 标准库正则实现性能一般,调试也麻烦。
典型误用是把简单字面量匹配写成正则,比如用 regex_replace(s, regex("\{\{name\}\}"), "") 替代直接 find+erase,纯属增加负担。
- 仅当模板片段含可变部分(如
"{{id:[0-9]+}}")或需全局替换时才考虑正则 - 正则字符串中的花括号、点号等必须转义,
"\{\{([^}]+)\}\}"才能捕获内容 - 若性能敏感,优先用循环调用
find+erase模拟“全局删”,避免重复构造 regex
用 std::string_view 避免拷贝,但不能删只能切
如果只是“逻辑上减去”片段(比如解析时跳过前缀),std::string_view 是零拷贝首选。但它不可变,无法真正删除字符,只提供视图偏移。
新手常混淆 string_view 和 string 的生命周期——一旦原字符串析构,string_view 就悬空。
- 用
string_view sv = s;后,sv.remove_prefix(7)或sv.remove_suffix(6)快速跳过 - 中间匹配需配合
find:例如size_t pos = sv.find("{{");,再用sv.substr(0, pos)+sv.substr(pos + 2)拼接(注意越界) - 最终要字符串结果?还是得转回
std::string,此时拷贝不可避免
实际项目里,“减去模板片段”的真实需求往往混着解析逻辑——比如删占位符后还要填值。这时候硬删不如用 std::format(C++20)或第三方模板引擎,避免在字符串上反复增删。边界条件、编码安全、多线程下的字符串所有权,这些比“怎么删”更值得花时间想清楚。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











