c++oding="utf-8" ?>
c++20 推荐用 std::erase(s, '%') 直接移除所有 '%' 字符;否则用 std::remove + erase 组合,避免 find 循环或正则替换。

用 std::erase 直接移除所有 '%' 字符(C++20)
如果你的项目已启用 C++20,std::erase 是最简洁安全的选择——它原地修改、不越界、不手动管理迭代器:
std::string s = "a%b%c%d%"; std::erase(s, '%'); // s 变成 "abcd"
注意:std::erase 对 std::string 重载只接受单个字符或值,不能传字符串字面量;传入 "%" 会编译失败(类型不匹配)。也别误用成 std::remove + erase 组合,那是 C++11/14 的写法,现在没必要绕弯。
兼容 C++11 的写法:用 std::remove + erase 惯用法
这是最广泛兼容且被大量旧代码验证过的方案。关键点在于:必须配对使用,单独调用 std::remove 只是重排,不会真正删字符:
-
std::remove把所有非'%'字符前移,返回新逻辑尾部的迭代器 - 紧接着用
string::erase从该位置删到结尾 - 别写成
s.erase(std::remove(...), s.end())—— 这是正确写法;写反了(比如漏掉s.end())会编译不过
std::string s = "x%y%z%"; s.erase(std::remove(s.begin(), s.end(), '%'), s.end());
避免用 find + erase 循环(易出错)
手写循环逐个查找删除看似直观,但极易引发越界或跳过字符:
-
std::string::find返回std::string::npos时,若没检查就直接传给erase,会触发未定义行为 - 每次
erase后后续字符前移,若用for递增索引,会跳过紧邻的下一个'%' - 反复
erase导致多次内存搬移,性能比一次remove+erase差得多
除非你明确需要在删除过程中做额外判断(比如只删偶数位置的 '%'),否则别碰这种写法。
正则替换不是好选择:过度杀伤且不可靠
有人想到用 std::regex_replace(s, std::regex("%"), ""),但实际没必要:
- 引入正则引擎开销大,编译慢,运行时慢,还可能因不同标准库实现(libstdc++ vs libc++)导致行为差异
-
"%"在正则里是特殊字符,虽然此处无歧义,但容易让人误以为要转义成"\%",反而写错 - 如果字符串里有其他正则元字符(如
"."、"*"),而你本意只是字面匹配,那正则更会偏离目标
纯字面字符删除,就该用字面匹配手段——std::erase 或 std::remove 是直觉对、效率高、无副作用的选择。
真正要注意的是:确认你的编译器和标准库支持 C++20 的 std::erase;如果还在用 GCC 9 或 Clang 10 以下版本,或者构建配置锁死了 C++17,那就老老实实用 remove + erase。别为了语法糖强行升级标准,反而让 CI 失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











