std::string::erase就地修改原串、不返回新串;最常用erase(pos,n)删从pos起的n个字符,pos越界抛异常,pos+n超长则自动截断;erase(pos)等价于erase(pos,npos)即删pos及之后全部。

erase函数的基本用法和参数含义
std::string::erase 是修改字符串内容的直接手段,它不返回新字符串,而是就地删除并返回 *this(支持链式调用)。最常用的是双参数重载:erase(size_t pos, size_t count) —— 从下标 pos 开始删 count 个字符。
注意:如果 pos 超出当前长度(size()),会抛出 std::out_of_range;如果 pos + count 超过长度,实际只删到末尾,不会报错。
常见误用:s.erase(2, 5) 在 "ab" 上执行会崩溃,因为 pos=2 已越界。
删除子串时如何安全计算起始位置和长度
想删掉某个子串(比如第一次出现的 "xyz"),不能硬写下标,得先用 find 定位:
立即学习“C++免费学习笔记(深入)”;
size_t p = s.find("xyz");
if (p != std::string::npos) {
s.erase(p, 3); // 明确传入子串长度,而非依赖 find 返回值当 count
}容易踩的坑:
-
find返回npos时直接传给erase→ 崩溃 - 用
s.erase(p, s.find("end") - p)这类动态算长度的表达式 → 若"end"没找到,find返回npos(极大值),减法会整数溢出变成超大正数,触发越界删 - 删完后原下标失效:连续删多个区间时,必须从前向后删,或每次重新
find
用迭代器删除范围要注意什么
另一个重载 erase(iterator first, iterator last) 更灵活,但迭代器有效性极敏感:
- 两个迭代器必须属于同一字符串,且
first - 删完后,所有指向被删位置及之后的迭代器全部失效(包括
end()) - 不能用
erase(it, it+3)删除 3 个字符后继续用it—— 它已无效 - 循环中边遍历边删?必须用
erase的返回值更新迭代器:it = s.erase(it, it+3),否则++it会解引用已失效地址
示例(安全跳过空格并删后续 2 字符):
for (auto it = s.begin(); it != s.end(); ) {
if (*it == ' ') {
it = s.erase(it, std::min(it + 2, s.end()));
} else {
++it;
}
}性能与替代方案的取舍
erase 是就地操作,通常比构造新字符串快,但底层可能触发内存搬移(尤其删开头/中间)。如果要删大量分散区间,拼接更高效:
- 多次
erase→ 时间复杂度可能 O(n²),因每次删都挪后续字符 - 改用
std::string result; for (… if (!to_skip) result += s[i]; …)→ 可预分配容量,避免反复 realloc - C++20 起可用
std::ranges::remove_if配合erase实现“逻辑删”:s.erase(std::ranges::remove_if(s, pred).begin(), s.end()),语义清晰但未必更快
真正关键的不是选哪个函数,而是别在未检查 find 结果、未校验迭代器范围、未处理 erase 后迭代器失效的情况下直接调用 erase —— 这些地方一错就是崩溃或未定义行为。


















