33

我理解使用std::string_view的动机;
它可以帮助避免在函数参数中进行不必要的分配。

例如:
以下程序将从std::string字符串文字创建一个。
这会导致不希望的动态分配,因为我们只对观察字符感兴趣。

#include <iostream>

void* operator new(std::size_t n)
{
    std::cout << "[allocating " << n << " bytes]\n";
    return malloc(n);
}

void observe_string(std::string const& str){}

int main(){
  observe_string("hello world"); //prints [allocating 36 bytes]
}

使用string_view将解决问题:

#include <iostream>
#include <experimental/string_view>

void* operator new(std::size_t n)
{
    std::cout << "[allocating " << n << " bytes]\n";
    return malloc(n);
}

void observe_string(std::experimental::string_view const& str){
}

int main(){
  observe_string("hello world"); //prints nothing
}

这给我留下了一个问题。
我什么时候会选择 std::string by const& 而不是 string_view 作为函数参数?

查看 的接口std::string_view,看起来我可以替换所有std::string通过的实例const&。这有什么反例吗?是std::string_view为了代替std::string const&参数传递吗?

4

4 回答 4

19

我什么时候会选择std::stringbyconst&而不是string_view函数参数?

需要一个以空字符结尾的字符串吗?如果是这样,那么您应该使用std::string const&which 为您提供保证。string_view没有 - 它只是一个const char.

如果您不需要以 null 结尾的字符串,并且您不需要拥有数据的所有权,那么您应该使用string_view. 如果您确实需要拥有数据的所有权,那么string按价值计算可能比string_view.

于 2017-08-13T16:27:43.130 回答
9

接受const std::string&而不是的一个可能原因string_view是当您想要存储对稍后可以更改的字符串对象的引用时。

如果您接受并存储 a ,则在内部缓冲区重新分配string_view时它可能会变得无效。string

如果您接受并存储对字符串本身的引用,则只要该对象处于活动状态,就不会出现该问题(您可能希望删除 r-value 引用重载,以避免临时对象出现明显问题)。

于 2017-08-13T16:59:38.457 回答
4

Andrei Alexandrescu 曾经说过,“没有工作胜过一些工作”。所以你应该const std::string&在这种情况下使用。因为std::string_view还涉及到一些工作(复制一对指针和长度)。

当然,const 引用可能仍然需要复制指针的成本;这几乎相当于std::string_view将要做什么。但是还有一项额外的工作std::string_view,它还复制了长度。

这是理论上的,但在实践中,将首选基准来推断性能


于 2016-09-19T03:08:03.167 回答
2

这并不是你真正要问的,但有时你想std::string 按价值而不是std::string_view出于性能原因。在这种情况下,您需要在检查字符串之前对其进行修改:

bool matches(std::string s)
{
  make_upper_case(s);
  return lib::test_if_matches(s);
}

无论如何,您都需要一个可变字符串,因此您可以将其声明为函数参数。如果您将其更改为std::string_view,并且有人传递了一个std::stringto 函数matches(),您将首先转换stringstring_view然后再转换string_viewstring,因此分配两次。

于 2018-06-19T08:50:43.277 回答