std::string::erase就地修改原字符串,不返回新串;最常用erase(pos,n),但erase(pos)因默认n=npos会删pos及之后全部字符,删单个需用erase(pos,1),安全删末尾用pop_back()。

直接说结论:std::string::erase 不返回新字符串,而是就地修改原对象;它有三种重载形式,最常用的是 erase(pos, n),但最容易出错的是下标越界和误以为 erase(pos) 只删一个字符。
为什么 erase(pos) 会清空后半截?
因为 erase(size_t pos) 的第二个参数默认是 npos(即极大值),等价于 erase(pos, npos) —— 从 pos 开始删到末尾。这不是“删第 pos 个字符”,而是“删 pos 及之后全部”。
- 想删单个字符?必须写成
erase(pos, 1) - 想删最后一个字符?用更安全的
pop_back()(无需计算下标,且不抛异常) - 若
pos == str.length(),调用erase(pos)合法(变成空串);但pos > str.length()就是未定义行为
erase(iterator) 和 erase(pos, n) 混用会崩溃吗?
不会自动崩溃,但极易引发迭代器失效或越界访问——尤其在循环中混用索引和迭代器时。
-
erase(pos, n)返回string&(自身引用),不改变其他索引语义 -
erase(iterator)返回下一个有效迭代器,**不能**再对原iterator做++,否则越界 - 常见错误:
for (auto it = s.begin(); it != s.end(); ++it) if (*it == 'x') s.erase(it);——erase后it失效,++it是野指针操作 - 正确写法:
for (auto it = s.begin(); it != s.end(); ) if (*it == 'x') it = s.erase(it); else ++it;
删除子串时,substr 和 erase 该怎么选?
看你要不要保留原字符串。两者语义完全不同:
-
substr是只读提取:生成新字符串,原串不变,适合“取一部分”场景(如取后6位身份证号) -
erase是就地破坏:原串被修改,适合“清理冗余”场景(如删掉中间某个标记段) - 性能上,
erase通常更省内存(不额外分配),但若你后续仍需原串,硬用erase再恢复反而更慢 - 别写
s = s.substr(0, pos) + s.substr(pos + n);来模拟删除——这创建了两个临时对象,比s.erase(pos, n)多一次拷贝
真正容易被忽略的点:所有 erase 重载都要求 pos ,哪怕 <code>n == 0;而 str.erase(str.length(), 0) 是合法的(无操作),但 str.erase(str.length() + 1, 0) 就是未定义行为——调试器未必报错,运行时可能静默崩坏。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











