【问题标题】:string_view as a parameter of const referencestring_view 作为 const 引用的参数
【发布时间】:2020-03-21 03:45:38
【问题描述】:

我见过带有以下签名的 std::string_view 代码:

void foo(std::string_view const &); // 1
void foo(std::string_view const);   // 2

哪个更正确?哪个更有效率? (我假设两者的答案是相同的)

【问题讨论】:

标签: c++ c++17


【解决方案1】:

理论上,由于string_view 是非拥有的,它已经可以被视为一个引用。因此,通过使用对 string_view 的引用,您将获得对引用的引用。

但它实际上似乎取决于您将编译器设置为的优化级别。 考虑以下代码:

#include <iostream>
#include <string_view>

void foo(std::string_view str) {
    std::cout << str;
}

void bar(std::string_view const &str){
    std::cout << str;
}

int main() {
    foo("test1");
    bar("test2");
}

foo 应该比bar 更有效率,对吧? 如果你使用 gcc 10.1 编译而不进行优化,你会得到 foobar 的以下程序集:

foo(std::basic_string_view<char, std::char_traits<char> >):
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     rax, rdi
        mov     rcx, rsi
        mov     rdx, rcx
        mov     QWORD PTR [rbp-16], rax
        mov     QWORD PTR [rbp-8], rdx
        mov     rdx, QWORD PTR [rbp-16]
        mov     rax, QWORD PTR [rbp-8]
        mov     rsi, rdx
        mov     rdx, rax
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >)
        nop
        leave
        ret
bar(std::basic_string_view<char, std::char_traits<char> > const&):
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     QWORD PTR [rbp-8], rdi
        mov     rax, QWORD PTR [rbp-8]
        mov     rdx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rax+8]
        mov     rsi, rdx
        mov     rdx, rax
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >)
        nop
        leave
        ret

可以看到foo 的操作比bar 多。似乎效率较低。 但是,如果将编译器优化设置为-O1,则会得到以下程序集

foo(std::basic_string_view<char, std::char_traits<char> >):
        sub     rsp, 8
        mov     rdx, rdi
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        add     rsp, 8
        ret
bar(std::basic_string_view<char, std::char_traits<char> > const&):
        sub     rsp, 8
        mov     rsi, QWORD PTR [rdi+8]
        mov     rdx, QWORD PTR [rdi]
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        add     rsp, 8
        ret

现在foo 需要少一次操作。

还要注意std::basic_string_view&lt;CharT,Traits&gt;::operator=](https://en.cppreference.com/w/cpp/string/basic_string_view/operator%3D) 的实现很奇怪也使用了const basic_string_view&amp;...

【讨论】:

    【解决方案2】:

    std::string_view 充当指向std::stringchar* C 字符串的指针。它包含一个指针和一个长度。没有必要通过引用传递它。始终使用一个值并复制它。

    永远不要将它存储在任何地方,或者如果你记得它是一个指针,而不是实际的东西。

    【讨论】:

      猜你喜欢
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 2020-08-12
      • 2019-12-10
      • 1970-01-01
      相关资源
      最近更新 更多