为什么 std::regex 比其他正则表达式库慢得多?

20 c++ regex benchmarking libstdc++ re2

这个 Github 存储库将 std::regex 添加到正则表达式引擎列表中,但被其他引擎淘汰了。

为什么 std::regex - 在 libstdc++ 中实现 - 比其他的慢得多?这是因为 C++ 标准要求还是只是特定的实现没有得到很好的优化?

同样在枪战中,即使添加了 std::regex::extended 标志,std::regex 也无法编译所有其他人都接受的几个正则表达式。他们是(?i)Twain、、、、和。\b\w+nn\b(?i)Tom|Sawyer|Huckleberry|Finn\s[a-zA-Z]{0,12}ing\s([A-Za-z]awyer|[A-Za-z]inn)\s\p{Sm}

更新:添加了与 boost::regex 的比较。

UPDATE2:添加了ctre

在此输入图像描述

Nic*_*las 21

这是因为 C++ 标准要求还是只是特定的实现没有得到很好的优化?

答案是肯定的。有点。

毫无疑问,libstdc++ 的实现<regex>没有得到很好的优化。但还有更多的事情要做。并不是标准要求抑制优化,而是标准要求抑制变化

正则表达式库是通过一堆模板定义的。char这允许人们在和之间进行选择wchar_t,这在理论上是好的。但有一个问题。

通过将代码直接复制并粘贴到针对这些库进行编译的代码中来使用模板库。由于模板的包含方式,即使是模板库之外的任何人都不知道的类型实际上也是库的 ABI 的一部分。如果更改它们,则针对不同版本的标准库编译的两个库将无法相互工作。由于正则表达式的模板参数是其字符类型,因此这些实现细节基本上涉及有关实现的所有内容。

当 libstdc++(和其他标准库实现)开始发布 C++ 正则表达式的实现时,它们将自己绑定到特定的实现,而该实现无法以影响库的 ABI 的方式进行更改。虽然它们可能会导致另一个 ABI 破坏来修复它,但标准库实现者不喜欢破坏 ABI,因为人们不会升级到破坏其代码的标准库。

当 C++11 禁止basic_string写时复制实现时,libstdc++ 出现了 ABI 问题。他们的 COW 字符串被广泛使用,更改它会使针对新字符串编译的代码在与针对旧字符串编译的代码一起使用时中断。libstdc++花了数年时间才真正实现了 C++11 字符串。

如果正则表达式是在没有模板的情况下定义的,则实现可以使用传统机制来隐藏实现细节。外部代码接口的 ABI 可以是固定且不变的,只有 ABI 背后的功能实现随版本的不同而变化。