std::string::erase 删除子串最直接,需指定起始位置和长度,支持链式调用但越界抛 std::out_of_range;常见错误是索引从0开始误判或长度超限导致自动截断。

用 std::string::erase 删除指定位置的子串最直接
只要知道起始位置和长度,erase 就能原地删掉对应子串,不产生额外拷贝。它返回 *this,支持链式调用,但注意:位置越界会抛 std::out_of_range 异常。
常见错误是把“删除第 n 个字符”理解成 erase(n, 1) 却忘了索引从 0 开始;或者传入的长度超出剩余字符数(比如字符串长 5,却写 erase(3, 10)),这时 erase 会自动截断为删到末尾,不报错但行为可能不符合预期。
-
s.erase(pos, len):从pos开始删len个字符;若len超出范围,实际只删到末尾 -
s.erase(pos):等价于s.erase(pos, std::string::npos),删从pos到结尾所有字符 - 确保
pos ,否则异常;<code>pos == s.length()是合法的(不删任何字符)
删子串前要先定位?用 find 配合 erase
如果目标不是“固定位置”,而是“删第一次出现的 "abc"”,就得先找位置。直接连用 find 和 erase 是惯用写法,但要注意 find 找不到时返回 std::string::npos,必须检查,否则传给 erase 会导致未定义行为(因为 npos 是极大值)。
示例:删掉首次出现的 "//" 及之后所有内容(类似注释截断):
s.erase(s.find("//"), std::string::npos);
这行看似简洁,但隐含风险——如果 s 不含 "//",find 返回 npos,erase(npos, npos) 会删整个字符串(因 npos 被当做大整数,触发越界截断逻辑)。稳妥写法是:
- 先存
size_t pos = s.find("//"); - 再判断
if (pos != std::string::npos) s.erase(pos);
删多个匹配子串?别用简单循环调 erase
想删所有 "xx",写 while ((pos = s.find("xx")) != npos) s.erase(pos, 2); 看似合理,实则危险:每次 erase 后后续字符前移,而 find 仍从开头搜,可能重复匹配同一位置(尤其当被删内容包含自身前缀时,如删 "aaa" 中所有 "aa"),还可能因反复移动内存影响性能。
更可靠的做法是反向查找(rfind)并删除,或构建新字符串:
- 反向删:
size_t pos; while ((pos = s.rfind("xx")) != std::string::npos) s.erase(pos, 2);,避免索引偏移干扰 - 重构法:
std::string res; size_t start = 0; while ((pos = s.find("xx", start)) != npos) { res += s.substr(start, pos - start); start = pos + 2; } res += s.substr(start); s = res;
注意 erase 的迭代器失效问题
如果代码中持有 std::string::iterator 或 char* 指针(比如 &s[0]),调用 erase 后它们全部失效。特别是用 for (auto it = s.begin(); it != s.end(); ++it) 边遍历边删,必然出错——删完后 it 指向已不存在的内存。
安全做法是删完重置迭代器,或改用下标循环并手动控制索引:
- 下标方式:
for (size_t i = 0; i - 迭代器方式:删完用
it = s.erase(it),它返回下一个有效位置;若删的是当前元素,不能继续++it
真正容易被忽略的是:即使没显式用迭代器,std::string 在小字符串优化(SSO)关闭、容量不足扩容时也会移动内存,导致所有外部指针失效——所以别长期缓存 &s[0] 或 s.data() 的结果用于后续 erase 操作。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











