我有一个关于使用 std::search
和 string::find
处理字符串的问题。我知道通常最好使用类特定成员函数算法而不是标准库算法,因为它可以基于类进行优化,但我想知道是否合理,比如为了保持一致性,使用迭代器而不是索引来使用 std::search
而非 string::find
。
如果我这样做会犯什么错误吗?还是应该坚持使用 string::find?从性能或风格方面来看,这两者之间有巨大的优势吗?
当前(2017年4月27日),至少GCC的libstdc++
(也是clang默认使用的)采用线性搜索实现std::string::find
,因此比使用Boyer-Moore算法或Knuth-Morris-Pratt算法等更慢。
std::string_view substr{"whatever"};
auto it = std::search(s.cbegin(), s.cend(),
std::boyer_moore_searcher(substr.begin(), substr.end()));
问题在于Boyer-Moore搜索器会为内部数据结构分配内存,因此可能会出现std::bad_alloc
异常。然而,std::string::find
被标记为noexcept
,因此在std::string::find
中使用已经实现的Boyer-Moore搜索器并不直接。
std::string::find
使用线性搜索? - Passer Bystd::string::find
以使用Boyer-Moore算法。因此,我认为这并不是标准规定的。 - Corristostd::string::find
是noexcept
的,但是Boyer-Moore需要为内部数据结构分配内存。我已经在答案中加入了这个说明。 - Corristostring::find
使用线性搜索,但对于某些情况(最新修补程序)比 Boyer-Moore 快数倍。我向 libstdc++ 和 libc++ 提交了一个修补程序(首元素再 memcomp),大大提高了 string::find
的性能。你可以尝试使用最新的 gcc(7.1),你会得到更好的性能表现。你也可以使用我编写的简单基准测试套件来测量性能:https://github.com/hiraditya/std-benchmark
特别是对于较小的字符串,在 Boyer-Moore 构造内部数据结构的时间内,(子)线性 string::find 就已经完成了。另外,在解析 HTML 等需要执行大量不匹配搜索的情况下,string::find 应该更快。
commit fc7ebc4b8d9ad7e2891b7f72152e8a2b7543cd65
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Mon Jan 9 13:05:58 2017 +0000
PR66414 optimize std::string::find
2017-01-09 Jonathan Wakely <jwakely@redhat.com>
Aditya Kumar <hiraditya@msn.com>
PR libstdc++/66414
* include/bits/basic_string.tcc
(basic_string::find(const CharT*, size_type, size_type)): Optimize.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244225 138bc75d-0d04-0410-961f-82ee72b054a4
提示:使用std :: find
总是比当前实现的std :: string :: find
慢。
std::string::find
可以使用 Boyer-Moore 算法等方法来加速查找。我不确定std::find
是否允许使用这样的方法。在处理字符串时,我建议仍然使用字符串版本。 - NathanOliverstd::string::find
与 Boyer-Moore 搜索器不兼容,而std::search
可以。或者你是指可以使用 Boyer-Moore 实现std::string::find
? - Corristostring::find
没有(至少在文档中没有正式说明)? - gowrathstd::string
时,使用索引是相当愚蠢的,因为这应该被认为是接口中的明显错误。如果符合您的审美选择并且不会极大地降低性能,我建议使用std::search
。 - Passer By