substr()最安全,不修改原串、返回新子串、越界返回空串;erase()原地修改、省内存但需防越界;replace()和手动循环低效且易错;unicode场景需专用库处理。

用 substr() 最安全直接
多数情况下,substr() 是最推荐的方式:它不修改原字符串,返回新子串,语义清晰且无副作用。比如想删掉前 3 个字符:s.substr(3) 就够了。
注意边界:如果 n 超过字符串长度,substr(n) 会返回空字符串 "",不会崩溃——这是 C++11 及以后的标准行为。但若传负数(比如 s.substr(-2)),编译直接报错,因为 substr 第二个参数是 size_t,不能为负。
- 要删前
n个字符,就写s.substr(n) -
n == 0时返回原串;n >= s.length()时返回空串 - 原字符串
s不变,适合函数式风格或需要保留原始数据的场景
用 erase() 原地修改更省内存
如果确定不再需要原字符串,用 erase() 修改自身更高效,尤其对大字符串或频繁操作时。调用 s.erase(0, n) 会从位置 0 开始删 n 个字符。
容易踩坑的是越界:如果 n > s.length(),erase(0, n) 会自动截断为 s.length(),结果是清空整个字符串——这行为合法但可能不符合预期。比如 "abc".erase(0, 10) 得到空串,不是报错。
- 写成
s.erase(0, n),不是s.erase(n)(后者删的是从位置n到末尾) - 如果
n来自用户输入或计算结果,建议先做std::min(n, s.length())防意外 - 修改原字符串,后续所有引用/指针都失效,多线程下需额外同步
别用 replace() 或手动循环拼接
有人试过 s.replace(0, n, ""),语法上可行,但语义绕弯、性能差(内部仍涉及构造临时空串和内存搬移),不如 erase() 直观高效。更糟的是手写循环:s = s.substr(n) 看似一样,但如果是 std::string_view 就不适用——它没有 substr() 的重载(C++20 才加),而 erase() 根本不存在。
-
std::string_view只能用remove_prefix(n),且不可逆(不能改原 view,只能生成新 view) - 如果代码要兼容
string和string_view,优先考虑统一用substr()或封装适配逻辑 - 手动
for循环拷贝剩余字符,既易出错又失去 STL 的优化保障
Unicode 字符串怎么办?
以上方法全按字节/码元操作,对 UTF-8 编码的中文、emoji 等会切碎字符。例如 "你好".substr(1) 可能返回乱码,因为一个汉字占 3 字节,删 1 字节只剩两个非法字节。
真要按“字符”删,得先用 ICU、utf8cpp 或 C++20 的 std::ranges::utf8_decode(需手动计数),没标准库捷径。所以实际项目中,除非明确要求 Unicode 意义上的“前 N 个字符”,否则默认按字节处理更简单可靠。
- 日志、协议解析、文件路径等场景,通常只需字节级截断,
substr/erase完全够用 - 用户界面文本操作才需真正字符计数,此时应引入专用 UTF-8 处理库,而非硬改 string 方法
- 别试图用
std::wstring+std::wcout绕过——Windows 下宽字符编码不统一,跨平台更麻烦
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











