std::string::substr 适合已知位置或长度时低开销截取,但需防越界;erase 适合原地删除以省内存,但要注意参数是位置/长度而非“删至某位置”。

用 std::string::substr 手动截取最直接
当明确知道前缀/后缀长度,或能定位起始位置时,substr 是开销最小的方式。它不修改原字符串,只返回新视图(C++17 起是真正视图,之前是拷贝)。
常见错误是越界调用:substr(pos, count) 中 pos 超出长度,或 pos + count 溢出,会抛 std::out_of_range。
- 删固定前缀(如
"pre_"):先用compare或starts_with(C++20)判断,再substr(4) - 删固定后缀(如
".txt"):检查size() >= 4 && s.compare(s.size()-4, 4, ".txt") == 0,再substr(0, s.size()-4) - 别直接写
s.substr(4)而不校验 —— 空串或短于 4 字符时必崩
std::string::erase 原地删更省内存
如果确定要修改原字符串且后续不再需要旧内容,erase 比 substr 更省内存(避免拷贝)。但它会触发内部重分配(如果容量远大于新长度),频繁调用可能有性能影响。
典型误用是混淆迭代器和索引:erase 接受的是迭代器范围或位置+长度,不是“删到某位置为止”。
- 删前缀:
s.erase(0, prefix_len),但必须确保prefix_len - 删后缀:
s.erase(s.size() - suffix_len),等价于erase(s.end() - suffix_len, s.end()) - C++20 可用
s.starts_with("abc")和s.ends_with("xyz")安全判断,再调erase
用 std::string_view 避免拷贝(C++17 起)
如果只是临时去掉前后缀用于比较、查找或传参,根本不需要构造新 std::string。string_view 的 remove_prefix 和 remove_suffix 是零成本操作,只移动指针。
注意:它不拥有数据,原字符串生命周期必须长于 string_view;也不能用于需要可变字符串的场景(如拼接、修改)。
- 安全做法:
std::string_view sv{s}; sv.remove_prefix(n); sv.remove_suffix(m); - 不能对
sv调data()后直接传给期望char*可写接口的 C 函数 - 和
substr不同,remove_prefix对空 view 或超长参数静默忽略(不抛异常),需自行校验逻辑合理性
处理 Unicode 或多字节编码时不能只看 size()
std::string::size() 返回字节数,不是字符数。若字符串含 UTF-8 中文、emoji 或其他多字节字符,按字节删前缀/后缀大概率切坏字符,导致乱码或解析失败。
没有标准库内置方案,必须引入外部处理(如 ICU、utf8cpp)或手动遍历 UTF-8 编码单元。
- 例如删前缀
"【":UTF-8 下它是 3 字节,但硬写substr(3)在 ASCII 环境下可行,在含中文上下文中极易出错 - 正则(
std::regex)也不解决这个问题 —— 它同样按字节匹配,且性能差、编译器支持不稳定 - 真实项目中,若涉及国际化,前缀/后缀应定义为
std::u8string(C++20)并用对应视图处理,或统一转为 Unicode code point 序列再操作
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











