第一个问题,是std::string::erase
重新分配吗?
第二个问题,有没有更快的方法来快速删除std::string
中的某些单词或短语?字符串的长度通常约为300K。
答案 0 :(得分:4)
如果string::erase
将触发重新分配,则无法定义。您可以通过比较string::capacity
与之后和调用方法之前进行检查,以查看发生的情况。删除部分字符串总是会触发删除部分后面的所有字符的副本,因为字符串的存储需要是连续的。
对于大字符串的操作,您可能需要考虑使用rope或std :: list。根据您的操作,这可能会更快。
答案 1 :(得分:4)
21.4.1 / 3
没有erase()或pop_back()成员函数会抛出任何异常。
由于分配器上不存在这样的限制,我认为可以肯定地说,不,std::string::erase
没有,也不能重新分配。
答案 2 :(得分:2)
您可能需要查看rope
。它是一个重型字符串(得到它吗?),专为大字符串设计,具有更快的子字符串操作。不幸的是,它不是std
的一部分,而是一个常见的添加(在SGI,STLPort和GNU的libstdc ++中)。
答案 3 :(得分:2)
已经提到过,它的实现依赖于std :: string :: erase是否会触发重新分配。所以我想专注于字符串搜索。解决此问题的传统方法是使用Aho-Corasick algorithm。
另外,David Musser使用Boyer-Moore和Knuth-Morris-Pratt算法的混合编写了一篇关于在大型草垛(弦)中搜索针(子串)的论文。该论文可用here。适应这一点可能比滚动Aho-Corasick实现更简单。
Musser的方法展示必须比天真的搜索和替换更快的行为。应该可以通过修改BM跳过循环和KNP查找表来调整算法以适应您的目的,以考虑您要替换的所有针。预先分配输出缓冲区,并通过向其添加haystack的所有不匹配段来迭代地构造输出字符串。随着针数的增加和BM / KNP查找的饱和,这种方法的效果会降低。
答案 4 :(得分:1)
从我对STL的实现中我可以看到std::string::erase
期间重新分配字符串的条件是:
if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
我认为这意味着在erase
调用期间字符串不会重新分配。
答案 5 :(得分:1)
std::string::erase
没有重新分配 - 因为它不需要,因为它是C ++哲学,你不需要支付(重新分配时间)你不需要的东西。要做的第一件事当然是找到一个快速算法来找到要删除的单词/短语。然后,如果只有一个要删除的块,std::string::erase
应该完全适合您的需要。
但是,例如,如果您有字符串“000aa11111bbbbb2222222c3333333333”并且想要删除包含字母的所有短语,则只需一个接一个地查找和删除它们将导致字符串其余部分的多个副本 - “1将被复制一次”, 2将被复制两次,依此类推。因此,如果字符串中有许多要删除的短语,则可以提高性能 - 只需复制应该单独保留在字符串中的块并覆盖要擦除的块:
(|表示字符串“正确”的迭代器):
这样,您必须在第一个删除的短语之后复制每个字符一次。
答案 6 :(得分:0)
我正在使用MS中的VC6,并且最后在std :: string :: erase()调用上重新分配缓冲区。 我不得不从我的代码中删除所有erase()调用,因为我有时使用大字符串,因此我发现了一些大的减速。 所以关心你的编译器并避免擦除()。就个人而言,我使用reaffectations str =“”; 作为一种解决方法。