C++20起可用std::erase(s, '')一行删除字符串中所有星号;此前需用erase-remove惯用法s.erase(remove(s.begin(),s.end(),''),s.end());不可变场景应手写循环+reserve构造新串。

用 std::erase 直接移除所有 '*'
C++20 起,std::string 支持 std::erase(非成员函数),一行就能删光所有星号,不用手动遍历或写循环:
std::string s = "a*b*c*d"; std::erase(s, '*'); // s 变成 "abcd"
这是最简洁、最安全的做法。注意它修改原字符串,不返回新串;如果需要保留原串,先拷贝一份再操作。
常见错误是误用 std::remove 单独调用(比如 std::remove(s.begin(), s.end(), '*')),这只会把星号挪到末尾,不真正缩短字符串长度——必须配合 erase 才生效,而 std::erase 已帮你封装好这一步。
兼容 C++17 或更早:用 erase-remove 惯用法
低于 C++20 的标准下,得手动组合 std::remove 和 erase:
立即学习“C++免费学习笔记(深入)”;
s.erase(std::remove(s.begin(), s.end(), '*'), s.end());
这个写法等价于 C++20 的 std::erase,但容易漏掉 s.end() 或写反参数顺序。几个关键点:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
std::remove不真的删除,只是重排:把所有非'*'元素前移,返回新逻辑结尾的迭代器 -
erase的第二个参数必须是s.end(),否则会删掉不该删的内容 - 不能对
const std::string使用,因为要修改原串
如果要保留原串并生成新字符串,别用 erase 系列
当原字符串不可变(比如传入的 const std::string&),或你想函数式地构造结果,就该用 std::copy_if 或范围 for:
std::string remove_asterisks(const std::string& s) {
std::string result;
result.reserve(s.length()); // 预分配避免多次扩容
for (char c : s) {
if (c != '*') result += c;
}
return result;
}
比起 std::copy_if + back_inserter,手写循环更直观、更容易控制容量。注意别省略 reserve——大量星号时,反复 += 可能触发多次内存重分配。
正则方式?能用但没必要
有人想到用 std::regex_replace(s, std::regex("\*"), ""),语法上没错,但代价高:
- 正则引擎启动开销大,哪怕只匹配单字符
- 编译器通常不优化掉这个开销,尤其在频繁调用场景(如解析日志)
-
"\*"中的双反斜杠容易写错,实际只需转义一次,但 regex 里*是元字符,必须写成"\*"或R"(*)"
除非你已经在用正则做更复杂的模式清洗,否则为删星号单独引入 regex,纯属杀鸡用牛刀。
真正要注意的是:星号在某些上下文中可能有语义(比如通配符、格式标记),直接全删前得确认业务是否允许——代码能跑通,不代表逻辑没坑。

















