V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhipengj
V2EX  ›  程序员

C++17 中的 std::string_view 性能远超 std::string

  •  
  •   zhipengj · 2018-09-23 03:12:50 +08:00 · 9338 次点击
    这是一个创建于 2014 天前的主题,其中的信息可能已经有所发展或是发生改变。

    周末正好看到一篇文章,讲 std::string_view 的性能,对于一些函数,其执行效率远远高于传统的 std::string。

    Use std::string_view to avoid string copy in C++17

    性能之所以这么好,很大程度上是由于 string_view 只提供了对原数据不可修改的指针,跳读的效率是远高于 string 的。

    附上其中一个 substr 操作的 benchmark 结果:

    img

    15 条回复    2018-09-24 05:53:31 +08:00
    geelaw
        1
    geelaw  
       2018-09-23 04:41:46 +08:00 via iPhone   ❤️ 7
    比较严重的错误:你写的那种从 char const * 构造 string_view 的写法并不是 O(1) 而是 Omega(length),因为你构造的时候就计算长度了。在很多情况下你看不出这个错误,是因为使用者通常也用了 Omega(n) 的时间。

    不是很严重的错误:一些拼写错误。

    一个小疑问:链接指向的是你自己的 blog 吗?你的这篇帖子的说法容易让人产生“链接不是指向你自己的 blog ”的错觉。
    Valyrian
        2
    Valyrian  
       2018-09-23 06:51:10 +08:00 via iPad
    用的时候条件也比较苛刻,指向的 string 必须全程在 scope 里,除了算 substring 真的没什么鸟用😂
    PureWhiteWu
        3
    PureWhiteWu  
       2018-09-23 07:45:51 +08:00
    怎么感觉是特意装成不是自己写的一样。。。。
    innoink
        4
    innoink  
       2018-09-23 07:57:56 +08:00 via Android
    这货在 boost 里早就有了 string_ref
    zn
        5
    zn  
       2018-09-23 08:09:02 +08:00 via iPhone
    这博客基本可以肯定是你自己的。那这文章是你自己写的吗?如果文章也是你自己写的,那感觉真是奇怪,毕竟你自己说的是 [周末看到一篇文章] 。难道是“我曾经得了精神分裂症,但是现在我们已经好了”的现实版?
    taowen
        6
    taowen  
       2018-09-23 08:13:48 +08:00
    虽然这么明显的是要推广自己的博客,但是鼓励一下吧。
    skadi
        7
    skadi  
       2018-09-23 09:19:33 +08:00
    "fuck"sv 只是 raw string 引用啊.
    这还要你强调性能么...
    yulon
        8
    yulon  
       2018-09-23 12:32:14 +08:00
    这还用测,只要满足 constexpr 的条件就是零开销,substr 也根本不会分配内存。
    wizardforcel
        9
    wizardforcel  
       2018-09-23 13:43:23 +08:00   ❤️ 1
    ( 1 )应该用 "..."s 和 "..."sv 来构造这些东西,把开销放在编译时间,省不少事。

    ( 2 )其实翻翻文档,你就知道它在干嘛了:

    string_view::string_view(const string_view&) 是 default

    https://zh.cppreference.com/w/cpp/string/basic_string_view/basic_string_view


    string_view::operator =(const string_view&)和 substr 复杂度为常数

    https://zh.cppreference.com/w/cpp/string/basic_string_view/operator%3D

    https://zh.cppreference.com/w/cpp/string/basic_string_view/substr
    wizardforcel
        10
    wizardforcel  
       2018-09-23 13:48:29 +08:00   ❤️ 1
    @geelaw 测不出来是因为它们都是 constexpr 的,也就是编译时进行的。所以怎么测都是折腾循环变量的时间。。。
    geelaw
        11
    geelaw  
       2018-09-23 19:09:03 +08:00
    @wizardforcel #10 constexpr 并不非要在编译期算出来。
    wizardforcel
        12
    wizardforcel  
       2018-09-23 19:33:55 +08:00 via Android
    geelaw
        13
    geelaw  
       2018-09-24 03:20:07 +08:00
    @wizardforcel #12 你的链接里的说明已经告诉你了。

    “ constexpr 指定符声明可以在编译时求得函数或变量的值。”

    只是可以,并没有要求必须计算出来。完整的标准里也没有要求 constexpr 必须在编译期计算出来。实际的实现也不一定。

    下面是 Visual C++ Compiler (cl.exe) 19.15.26726 for x64 的实验 http://codepad.org/Yw4Q8FNn

    另一个你没注意到的错误是,字符串字面量作为 char const * 传入 constexpr 函数的时候永远不会有 constexpr 的效果。正确的实现是使用数组并用模板参数控制数组长度,当然为了兼容进来的是指针、数组、空指针等等各种情况,你需要用偏特化。下面的代码是一个范例:

    http://codepad.org/MSqAmd5R
    geelaw
        14
    geelaw  
       2018-09-24 03:24:55 +08:00
    @geelaw #13 一开始第二个链接的代码有点小错误(没有初始化数组导致 undefined behaviour )。这里是修正的版本:

    http://codepad.org/X2D62VwD
    geelaw
        15
    geelaw  
       2018-09-24 05:53:31 +08:00
    @wizardforcel
    @geelaw
    @geelaw #12 #13 #14

    Oopsy 我搞了一个严重的错误 - - c.cc 的第 8 行我写错了才会导致直接用 char const * 不行,实际上是可以的。我需要收回 13 的后半段。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2939 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 14:04 · PVG 22:04 · LAX 07:04 · JFK 10:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.