最直接、安全、推荐的方式是使用 C++20 的 std::erase;它自动完成查找与移除,原地修改字符串,时间复杂度 O(n),不返回新对象且不改变原对象地址。

用 std::erase 删除所有 '+' 字符(C++20 及以上)
最直接、安全、推荐的方式是使用 C++20 引入的 std::erase,它自动完成查找 + 移除的全部逻辑,无需手动管理迭代器:
-
std::erase会原地修改字符串,时间复杂度 O(n),内部已做优化 - 不返回新字符串,也不改变原有对象地址,适合频繁操作场景
- 若编译器不支持 C++20(如 GCC ‘erase’ is not a member of ‘std’
std::string s = "a+b+c+"; std::erase(s, '+'); // s 变成 "abc"
用 std::remove_if + erase(兼容 C++11)
这是 C++11 起广泛使用的“erase–remove 惯用法”,需两步:先移位再截断。容易出错的地方在于漏掉第二步 erase:
- 只调
std::remove_if(s.begin(), s.end(), [](char c){ return c == '+'; })不会真正删字符,只是把非'+'的移到前面,末尾留垃圾 - 必须配合
s.erase(...)才算完成删除 - 注意
std::remove_if返回的是新逻辑结尾的迭代器,不是布尔值或计数
std::string s = "x+y+z+";
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return c == '+'; }), s.end());
// s 变成 "xyz"
避免用 replace 或 find+erase 循环
这类写法看似直观,但效率低、易崩溃,常见于新手代码:
-
s.replace(pos, 1, "")在长字符串中反复调用,每次都要内存搬移,O(n²) 时间 -
while ((pos = s.find('+')) != std::string::npos)中,若s为空或没找到,find返回std::string::npos(极大值),强制转为size_t后传给erase可能触发越界断言(尤其在 libstdc++ debug 模式下) - 循环中未更新
pos或未处理重复匹配位置,会导致跳过相邻加号(如"++"只删一个)
注意空字符串和连续加号的边界行为
所有正确方法对极端输入都应健壮,但实际中仍有人忽略:
立即学习“C++免费学习笔记(深入)”;
-
std::erase(s, '+')对空串""安全,无副作用 - 输入为纯加号如
"++++",结果应为""——std::remove_if方案中若误写s.erase(s.begin(), s.end())会清空整个串,但这是正确的;错误在于用错迭代器范围 - 若字符串含宽字符或 UTF-8 多字节加号(如某些编码下的全角+),
'+'匹配只针对 ASCII,不会误删,但也**不会**匹配那些 Unicode 加号;需要 Unicode 处理时得换用 ICU 或std::wstring+std::erase配合宽字符
std::erase,以及有没有在 remove_if 后忘掉 erase 这一步。


















