在这种情况下,使用 string_view 会导致不必要的字符串复制吗?

Does using string_view lead to an unnecessary string copy in this scenario?

我想要做的是让我的 class 在构建期间接受一个字符串。我读到 string_viewconst string& 的替代品,所以我很自然地写了一个这样的构造函数。这允许我接受 C++ 和 C 字符串。

Url::Url(boost::string_view raw_url)
    : url_(static_cast<std::string>(raw_url)) {

这里可能存在的问题是,当传递一个右值时,有一个不必要的复制而不是一个移动。是制作另一个采用 string&& 的构造函数的解决方案吗?这里的最佳做法是什么?

注意:我会考虑 std::string_view 来写答案,但 boost::string_view 应该是相似的。


I read that string_view was a replacement for const string&

了解为什么首先添加 std::string_view 的原因很有用。

const string&有什么问题?

如果你传递一个std::string对象而你对std::string_view没有任何收获,那肯定是有效的。但是现在假设您正在传递一个包含大字符串的 char*。在这种情况下,将创建一个临时 std::string 对象(并且将复制该 char* 引用的整个字符串),以便函数接收 std::string。那是 std::string_view 闪耀的时候。如果将 char*std::string(或任何可以转换为 std::string_view 的东西)传递给接受 std::string_view 的函数(按值,不需要接受 std::string_view 通过引用)然后创建的新 std::string_view 对象非常便宜,因为它只是 "a view" 并且它不复制底层字符串。


但你的情况不同。由于你无论如何都在复制字符串,那么你的函数应该只接受一个字符串by value并将字符串移动到函数内部。比如

Url::Url(std::string raw_url)
    : url_(std::move(raw_url)) {

还有一个clang-tidy warning告诉你这个

优点是,如果你的函数的用户传递了一个左值,你就制作了一个副本(无论如何你都需要它)和一个移动,但是如果他们传递了一个右值,那么就没有副本,只有一个移动。