• c++17 string_view


    string_view: No such file or directory

     std::string_view is not available in GCC until version 7.

    root@ubuntu:~/c++# gcc --version
    gcc (Ubuntu/Linaro 5.5.0-12ubuntu1) 5.5.0 20171010
    Copyright (C) 2015 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    root@ubuntu:~/c++# 
    configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.
    root@cloud:~/gcc-7.5.0# ./contrib/download_prerequisites
    2021-07-02 15:02:50 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 [2383840] -> "./gmp-6.1.0.tar.bz2" [1]
    2021-07-02 15:02:59 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2 [1279284] -> "./mpfr-3.1.4.tar.bz2" [1]
    2021-07-02 15:03:05 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz [669925] -> "./mpc-1.0.3.tar.gz" [1]
    2021-07-02 15:03:15 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.16.1.tar.bz2 [1626446] -> "./isl-0.16.1.tar.bz2" [1]
    gmp-6.1.0.tar.bz2: OK
    mpfr-3.1.4.tar.bz2: OK
    mpc-1.0.3.tar.gz: OK
    isl-0.16.1.tar.bz2: OK
    All prerequisites downloaded successfully.
    root@cloud:~/gcc-7.5.0# 
    root@cloud:~/gcc-7.5.0# mkdir  gcc-build-7.5
    root@cloud:~/gcc-7.5.0# cd gcc-build-7.5/
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# ../configure --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --enable-gnu-indirect-function --with-tune=generic --disable-multilib 
    root@cloud:~/gcc-7.5.0# ./contrib/download_prerequisites
    2021-07-02 15:02:50 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 [2383840] -> "./gmp-6.1.0.tar.bz2" [1]
    2021-07-02 15:02:59 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2 [1279284] -> "./mpfr-3.1.4.tar.bz2" [1]
    2021-07-02 15:03:05 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz [669925] -> "./mpc-1.0.3.tar.gz" [1]
    2021-07-02 15:03:15 URL: ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.16.1.tar.bz2 [1626446] -> "./isl-0.16.1.tar.bz2" [1]
    gmp-6.1.0.tar.bz2: OK
    mpfr-3.1.4.tar.bz2: OK
    mpc-1.0.3.tar.gz: OK
    isl-0.16.1.tar.bz2: OK
    All prerequisites downloaded successfully.
    root@cloud:~/gcc-7.5.0# cd -
    /root/gcc-7.5.0/gcc-build-7.5
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# ../configure --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --enable-gnu-indirect-function --with-tune=generic --disable-multilib   
    checking build system type... aarch64-unknown-linux-gnu
    checking host system type... aarch64-unknown-linux-gnu
    checking target system type... aarch64-unknown-linux-gnu
    checking for a BSD-compatible install... /usr/bin/install -c
    checking whether ln works... yes
    checking whether ln -s works... yes
    checking for a sed that does not truncate output... /bin/sed
    checking for gawk... gawk
    checking for libatomic support... yes
    checking for libcilkrts support... no
    checking for libitm support... yes
    checking for libsanitizer support... yes
    checking for libvtv support... yes
    checking for libmpx support... no
    checking for libhsail-rt support... no
    checking if mkdir takes one argument... no
    This target does not support --with-tune.
    Valid --with options are: abi cpu arch
    Makefile:4282: recipe for target 'configure-stage1-gcc' failed
    make[2]: *** [configure-stage1-gcc] Error 1
    make[2]: Leaving directory '/root/gcc-7.5.0/gcc-build-7.5'
    Makefile:25895: recipe for target 'stage1-bubble' failed
    make[1]: *** [stage1-bubble] Error 2
    make[1]: Leaving directory '/root/gcc-7.5.0/gcc-build-7.5'
    Makefile:939: recipe for target 'all' failed
    make: *** [all] Error 2
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# 

    configure的最后一个参数是关闭32位库,只编译64位库, 。如果想要同时编译32位和64位,可以使用-enable-multilib
    ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
     

     编译通过

    make install
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# ls /usr/local/bin | grep gcc
    aarch64-unknown-linux-gnu-gcc
    aarch64-unknown-linux-gnu-gcc-7.5.0
    aarch64-unknown-linux-gnu-gcc-ar
    aarch64-unknown-linux-gnu-gcc-nm
    aarch64-unknown-linux-gnu-gcc-ranlib
    gcc
    gcc-ar
    gcc-nm
    gcc-ranlib
    -rwxr-xr-x 3 root root 5771384 Jul  2 17:43 /usr/local/bin/aarch64-unknown-linux-gnu-gcc-7.5.0
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# ls -al  /usr/local/bin/aarch64-unknown-linux-gnu-gcc
    -rwxr-xr-x 3 root root 5771384 Jul  2 17:43 /usr/local/bin/aarch64-unknown-linux-gnu-gcc
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# ls -al  /usr/local/bin/gcc
    -rwxr-xr-x 3 root root 5771384 Jul  2 17:43 /usr/local/bin/gcc
    root@cloud:~/gcc-7.5.0/gcc-build-7.5#   /usr/local/bin/gcc -v
    Using built-in specs.
    COLLECT_GCC=/usr/local/bin/gcc
    COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/aarch64-unknown-linux-gnu/7.5.0/lto-wrapper
    Target: aarch64-unknown-linux-gnu
    Configured with: ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
    Thread model: posix
    gcc version 7.5.0 (GCC) 
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# 
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# find /usr -name "libstdc++.so*"
    /usr/local/lib64/libstdc++.so
    /usr/local/lib64/libstdc++.so.6.0.24-gdb.py
    /usr/local/lib64/libstdc++.so.6.0.24
    /usr/local/lib64/libstdc++.so.6
    /usr/lib/gcc/aarch64-linux-gnu/5/libstdc++.so
    /usr/lib/gcc/aarch64-linux-gnu/7/libstdc++.so
    /usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.25
    /usr/lib/aarch64-linux-gnu/libstdc++.so.6
    /usr/share/gdb/auto-load/usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.25-gdb.py
    root@cloud:~/gcc-7.5.0/gcc-build-7.5# 

     g++ -O0 -o static_str str_vier.cpp -std=c++17 -g && objdump -S -t -D static_str > static_str.s

    #include<string>
    #include<string_view>
    using namespace std;
    int main()
    {
      40150c:       a9b87bfd        stp     x29, x30, [sp, #-128]!
      401510:       910003fd        mov     x29, sp
      401514:       f9000bf3        str     x19, [sp, #16]
            //指针指向静态字符串
            const char* str_ptr = "this is a static string";
      401518:       90000000        adrp    x0, 401000 <_init-0x2c0>
      40151c:       913ee000        add     x0, x0, #0xfb8
      401520:       f9003fa0        str     x0, [x29, #120]
    
            //字符串数组
            char str_array[] = "this is a static string";
      401524:       90000000        adrp    x0, 401000 <_init-0x2c0>
      401528:       913ee000        add     x0, x0, #0xfb8
      40152c:       910163a2        add     x2, x29, #0x58
      401530:       aa0003e3        mov     x3, x0
      401534:       a9400460        ldp     x0, x1, [x3]
      401538:       a9000440        stp     x0, x1, [x2]
      40153c:       f9400860        ldr     x0, [x3, #16]
      401540:       f9000840        str     x0, [x2, #16]
            //std::string
            std::string str = "this is a static string";
      401544:       9101c3a0        add     x0, x29, #0x70
      401548:       97ffffa6        bl      4013e0 <_ZNSaIcEC1Ev@plt>
      40154c:       9101c3a2        add     x2, x29, #0x70
      401550:       90000000        adrp    x0, 401000 <_init-0x2c0>
      401554:       913ee001        add     x1, x0, #0xfb8
      401558:       9100e3a0        add     x0, x29, #0x38
      40155c:       94000075        bl      401730 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_>
      401560:       9101c3a0        add     x0, x29, #0x70
      401564:       97ffff8b        bl      401390 <_ZNSaIcED1Ev@plt>
            //std::string_view
            std::string_view sv = "this is a static string";
      401568:       d28002e0        mov     x0, #0x17                       // #23
      40156c:       f90017a0        str     x0, [x29, #40]
      401570:       90000000        adrp    x0, 401000 <_init-0x2c0>
      401574:       913ee000        add     x0, x0, #0xfb8
      401578:       f9001ba0        str     x0, [x29, #48]
            std::string str = "this is a static string";
      40157c:       9100e3a0        add     x0, x29, #0x38
      401580:       94000062        bl      401708 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev>
    }
    #include<string>
    #include<string_view>
    using namespace std;
    int main()
    {
            //指针指向静态字符串
            const char* str_ptr = "this is a static string";
    
            //字符串数组
            char str_array[] = "this is a static string";
            //std::string
            std::string str = "this is a static string";
            //std::string_view
            std::string_view sv = "this is a static string";
    }

    当字符串数据的所有权已经确定(譬如由某个string对象持有),并且你只想访问(而不修改)他们时,使用 std::string_view 可以避免字符串数据的复制,从而提高程序效率,这(指程序效率)也是这篇文章的主要内容.

    这次要介绍的 string_view 是 C++17 的一个主要特性.

    我假设你已经了解了一些 std::string_view 的知识,如果没有,可以看看我之前的这篇文章.C++ 中的 string 类型在堆上存放自己的字符串数据,所以当你处理 string 类型的时候,很容易就会产生(堆)内存分配.

    Small string optimisation

    我们先看下以下的示例代码:

     1 #include <iostream>
     2 #include <string>
     3 
     4 void* operator new(std::size_t count) 
     5 {
     6     std::cout << "   " << count << " bytes" << std::endl;
     7     return malloc(count);
     8 }
     9 
    10 void getString(const std::string& str) {}
    11 
    12 int main()
    13 {
    14     std::cout << std::endl;
    15 
    16     std::cout << "std::string" << std::endl;
    17 
    18     std::string small = "0123456789";
    19     std::string substr = small.substr(5);
    20     std::cout << "   " << substr << std::endl;
    21 
    22     std::cout << std::endl;
    23 
    24     std::cout << "getString" << std::endl;
    25 
    26     getString(small);
    27     getString("0123456789");
    28     const char message[] = "0123456789";
    29     getString(message);
    30 
    31     std::cout << std::endl;
    32     
    33     return 0;
    34 }

    代码第4到第8行,我重载了全局的 new 操作符,这样我就能跟踪(堆)内存的分配了,而后,代码分别在第18行,第19行,第27行,第29行创建了string对象,所以这几处代码都会产生(堆)内存分配.相关的程序输出如下:

    root@cloud:~/c++# ./srV1 
    
    std::string
       56789
    
    getString
    
    root@cloud:~/c++# 

    咦, 程序竟然没有产生内存分配?这是怎么回事?其实 string 类型只有在字符串超过指定大小(具体实现相关)时才会申请(堆)内存,对于 MSVC 来说,指定大小为 15, 对于 GCC 和 Clang,这个值则为 23.

    这也就意味着,较短的字符串数据是直接存储于 string 的对象内存中的,不需要分配(堆)内存.

    从现在开始,示例代码中的字符串将拥有至少30个字符,这样我们就不需要关注短字符串优化了.好了,带着这个前提(字符串长度>=30个字符),让我们重新开始讲解.

    #include <iostream>
    #include <string>
    
    void* operator new(std::size_t count)
    {
            std::cout << "   " << count << " bytes" << std::endl;
            return malloc(count);
    }
    
    void getString(const std::string& str) {}
    
    int main()
    {
            std::cout << std::endl;
    
            std::cout << "std::string" << std::endl;
    
            std::string small = "0123456789#0123456789#0123456789#0123456789#0123456789";
            std::string substr = small.substr(5);
            std::cout << "   " << substr << std::endl;
    
            std::cout << std::endl;
    
            std::cout << "getString" << std::endl;
    
            getString(small);
            getString("0123456789");
            const char message[] = "0123456789";
            getString(message);
    
            std::cout << std::endl;
    
            return 0;
    }
    root@cloud:~/c++# ./srV1 
    
    std::string
       55 bytes
       50 bytes
       56789#0123456789#0123456789#0123456789#0123456789
    
    getString
    #include <iostream>
    #include <string>
    
    void* operator new(std::size_t count)
    {
            std::cout << "   " << count << " bytes" << std::endl;
            return malloc(count);
    }
    
    void getString(const std::string& str) {}
    
    int main()
    {
            std::cout << std::endl;
    
            std::cout << "std::string" << std::endl;
    
            std::string small = "0123456789#0123456789#0123456789#0123456789#0123456789";
            getString(small);
            getString("01234567890123456789#0123456789#0123456789#0123456789#0123456789");
            const char message[] = "01234567890123456789#0123456789#0123456789#0123456789#0123456789$$$$$$$$$$$$$";
            getString(message);
    
            std::cout << std::endl;
    
            return 0;
    }
    root@cloud:~/c++# g++ -std=c++17 -g strV1.cpp -o   srV1
    root@cloud:~/c++# ./srV1 
    
    std::string
       55 bytes
       65 bytes
       78 bytes
    
    root@cloud:~/c++#
    #include <iostream>
    #include <string>
    #include <string_view>
    
    void* operator new(std::size_t count)
    {
            std::cout << "   " << count << " bytes" << std::endl;
            return malloc(count);
    }
    
    void getString(const std::string& str) {}
    
    int main()
    {
            std::cout << std::endl;
    
            std::cout << "std::string" << std::endl;
    
            std::string large= "0123456789#0123456789#0123456789#0123456789#0123456789";
    
            std::string_view largeStringView{ large.c_str(), large.size() };
            std::cout << std::endl;
    
            return 0;
    }
    root@cloud:~/c++# g++ -std=c++17 -g strV1.cpp -o   srV1
    root@cloud:~/c++# ./srV1 
    
    std::string
       55 bytes

    No memory allocation required

    现在, std::string_view 无需复制字符串数据的优点就更加明显了(std::string不进行短字符串优化的情况下),下面的代码就是例证.

     1 #include <cassert>
     2 #include <iostream>
     3 #include <string>
     4 #include <string_view>
     5 
     6 void* operator new(std::size_t count) 
     7 {
     8     std::cout << "   " << count << " bytes" << std::endl;
     9     return malloc(count);
    10 }
    11 
    12 void getString(const std::string& str) {}
    13 
    14 void getStringView(std::string_view strView) {}
    15 
    16 int main()
    17 {
    18     std::cout << std::endl;
    19 
    20     std::cout << "std::string" << std::endl;
    21 
    22     std::string large = "0123456789-123456789-123456789-123456789";
    23     std::string substr = large.substr(10);
    24 
    25     std::cout << std::endl;
    26 
    27     std::cout << "std::string_view" << std::endl;
    28 
    29     std::string_view largeStringView{ large.c_str(), large.size() };
    30     largeStringView.remove_prefix(10);
    31 
    32     assert(substr == largeStringView);
    33 
    34     std::cout << std::endl;
    35 
    36     std::cout << "getString" << std::endl;
    37 
    38     getString(large);
    39     getString("0123456789-123456789-123456789-123456789");
    40     const char message[] = "0123456789-123456789-123456789-123456789";
    41     getString(message);
    42 
    43     std::cout << std::endl;
    44 
    45     std::cout << "getStringView" << std::endl;
    46 
    47     getStringView(large);
    48     getStringView("0123456789-123456789-123456789-123456789");
    49     getStringView(message);
    50 
    51     std::cout << std::endl;
    52     
    53     return 0;
    54 }
    root@cloud:~/c++# mv controller.yaml  strV2.cpp
    root@cloud:~/c++# g++ -std=c++17 -g strV2.cpp -o   srV2
    root@cloud:~/c++# ./srV2
    
    std::string
       41 bytes
       31 bytes
    
    std::string_view
    
    getString
       41 bytes
       41 bytes
    
    getStringView
    #include <iostream>
    #include <string>
    #include <string_view>
    #include <cassert>
    
    void* operator new(std::size_t count) 
    {
            std::cout << "   " << count << " bytes" << std::endl;
            return malloc(count);
    }
    
    void getString(const std::string& str) {}
    
    int main()
    {
            std::cout << std::endl;
    
            std::cout << "std::string" << std::endl;
    
            std::string large= "0123456789#0123456789#0123456789#0123456789#0123456789";
            std::string substr = large.substr(10);
            std::cout << std::endl;
            std::cout << "std::string_view" << std::endl;
    
            std::string_view largeStringView{ large.c_str(), large.size() };
            largeStringView.remove_prefix(10);
            assert(substr == largeStringView);
            std::cout << substr << std::endl;
            std::cout << largeStringView << std::endl;
    
            std::cout << std::endl;
    
            std::cout << "getString" << std::endl;
            retu
    root@cloud:~/c++# ./srV1 
    
    std::string
       55 bytes
       45 bytes
    
    std::string_view
    #0123456789#0123456789#0123456789#0123456789
    #0123456789#0123456789#0123456789#0123456789
    #include <iostream>
    #include <string>
    #include <string_view>
    #include <cassert>
    
    void* operator new(std::size_t count)
    {
            std::cout << "   " << count << " bytes" << std::endl;
            return malloc(count);
    }
    
    void getString(const std::string& str) {}
    void getStringView(std::string_view strView) {}
    
    int main()
    {
            std::cout << std::endl;
    
            std::cout << "std::string" << std::endl;
    
            std::string large= "0123456789#0123456789#0123456789#0123456789#0123456789";
            std::cout << std::endl;
            std::cout << "std::string_view" << std::endl;
    
            std::string_view largeStringView{ large.c_str(), large.size() };
            std::cout << std::endl;
            std::cout << "getString" << std::endl;
            //getString(large);
            //getString("0123456789-123456789-123456789-123456789");
            const char message[] = "0123456789-123456789-123456789-123456789";
            //getString(message);
            std::cout << std::endl;
            std::cout << "getStringView" << std::endl;
            getStringView(large);
            getStringView("0123456789-123456789-123456789-123456789");
            getStringView(message);
            std::cout << std::endl;
            return 0;
    }
    root@cloud:~/c++# g++ -std=c++17 -g strV1.cpp -o   srV1
    root@cloud:~/c++# ./srV1 
    
    std::string
       55 bytes
    
    std::string_view
    
    getString
    
    getStringView

     C++17,使用 string_view 来避免复制

    使用std::string_view和tokenizer提升字符串处理性能

    C++17剖析:string_view的实现,以及性能

    gcc 5.2.0 手动更新(亲测)

  • 相关阅读:
    典型用户和用户场景
    每日站立会议个人博客(冲刺周)-Tuesday
    WPS中VB编辑器的安装
    WARN hdfs.DataStreamer: Caught exception
    java.net.ConnectException: Your endpoint configuration is wrong; For more details see: http://wiki.apache.org/hadoop/UnsetHostnameOrPort
    “初始化 Java 工具”期间发生了内部错误, java.lang.NullPointerException
    在Github上搭建个人主页
    关于新版的MySQL安装教程
    stopping hbasecat:/tmp/hbase-root-master.pid:No such file or directory
    途牛订单的服务化演进
  • 原文地址:https://www.cnblogs.com/dream397/p/14963442.html
Copyright © 2020-2023  润新知