为什么将`const char [N]`和`const char*`传递给view :: c_str()会产生不同的二进制文件,而string_view会产生相同的结果吗?

san*_*orn 5 c++ optimization range-v3 string-view

随着std::string_view,与两者range::for_each产生精确组装const char[N]const char *传递给std::string_viewctor

换句话说,这段代码

auto str = "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n";
ranges::for_each(std::string_view{str}, std::putchar);
Run Code Online (Sandbox Code Playgroud)

auto& str = "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n";
ranges::for_each(std::string_view{str}, std::putchar);
Run Code Online (Sandbox Code Playgroud)

两者都低于汇编:

main:                                   # @main
        pushq   %rbx
        movq    $-90, %rbx
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
        movsbl  .L.str+90(%rbx), %edi
        movq    stdout(%rip), %rsi
        callq   _IO_putc
        addq    $1, %rbx
        jne     .LBB0_1
        xorl    %eax, %eax
        popq    %rbx
        retq
.L.str:
        .asciz  "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n"
Run Code Online (Sandbox Code Playgroud)

此外,如果我们通过交流字符串const char[N]ranges::view::c_str(),

auto& str = "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n";
ranges::for_each(ranges::view::c_str(str), std::putchar);
Run Code Online (Sandbox Code Playgroud)

这就产生了像上面那样产生的精确装配std::string_view.


在另一方面,如果我们经过交流字符串const char*ranges::view::c_str()

auto str = "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n";
ranges::for_each(ranges::view::c_str(str), std::putchar);
Run Code Online (Sandbox Code Playgroud)

这次它产生一个不同的组件如下:

main:                                   # @main
        pushq   %rbx
        movb    $116, %al
        movq    $-90, %rbx
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
        movsbl  %al, %edi
        movq    stdout(%rip), %rsi
        callq   _IO_putc
        movzbl  .L.str+91(%rbx), %eax
        incq    %rbx
        jne     .LBB0_1
        xorl    %eax, %eax
        popq    %rbx
        retq
.L.str:
        .asciz  "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n"
Run Code Online (Sandbox Code Playgroud)

哪个组装胜利?

为什么std::string_view决定产生相同的二进制文件?

能否view::c_str()既产生只有一个更快的组装const char*const char [N]

godbolt.org/g/wcQyY1

Jon*_*ely 5

两个std::string_view版本都调用相同的构造函数,它const char*使用a 然后使用std::char_traits::length(基本上是strlen)来查找长度.编译器优化掉了strlen因为字符串文字对于编译器是可见的,因此它的长度是已知的,但是两种形式都使用完全相同的构造函数,并且两者都优化掉了strlen,因此两者都生成相同的代码.

view::c_str版本使用不同的重载,具体取决于它是指针还是数组,请参阅https://github.com/ericniebler/range-v3/blob/1f4a96e9240786801e95a6c70afebf27f04cffeb/include/range/v3/view/c_str.hpp#L68

当给定指针时,它必须找到与使用类似的长度strlen,但是当给定一个大小的数组时,NN-1用于长度.即使编译器strlen将类似代码优化为固定的编译时值,它仍然在编译不同的东西,因此生成的代码不相同并不奇怪.