在这种情况下,使用 string_view 会导致不必要的字符串复制吗?
Posted
技术标签:
【中文标题】在这种情况下,使用 string_view 会导致不必要的字符串复制吗?【英文标题】:Does using string_view lead to an unnecessary string copy in this scenario? 【发布时间】:2020-05-28 20:12:02 【问题描述】:我想做的是让我的班级在构造过程中接受一个字符串。我读到string_view
是const string&
的替代品,所以我很自然地写了一个这样的构造函数。这让我可以接受 c++ 和 c 字符串。
Url::Url(boost::string_view raw_url)
: url_(static_cast<std::string>(raw_url))
这里可能存在的问题是,当传递一个右值时,会有一个不必要的副本而不是移动。是制作另一个采用string&&
的构造函数的解决方案吗?这里的最佳做法是什么?
【问题讨论】:
应该移入一些数据的构造函数通常只接受值,而不是右值引用。这更简单。 创建一个构造函数,按值获取参数并将其移动到url_
。
重点是移入会员url_(std::move(raw_url))
,那么你只会得到一份。对于左值,您将获得额外的移动,但您只需要编写一个处理所有情况的构造函数。与我猜想的更多样板代码相比,这取决于额外移动对性能的重要性。
【参考方案1】:
注意:我会考虑std::string_view
来写答案,但boost::string_view
应该是相似的。
我读到 string_view 是 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
),那么新的@创建的 987654338@ 对象非常便宜,因为它只是“一个视图”,它不会复制底层字符串。
但你的情况不同。由于您无论如何都在复制字符串,那么您的函数应该只接受一个字符串按值并将字符串移动到函数内。诸如
之类的东西Url::Url(std::string raw_url)
: url_(std::move(raw_url))
甚至还有clang-tidy warning 告诉你这一点。
优点是,如果你的函数的用户传递了一个左值,你会创建一个副本(无论如何你都需要它)和一个移动,但如果他们传递一个右值,那么就没有副本,只有一个移动。
【讨论】:
这不是等效代码 - 此类函数不接受string_view
作为参数。
你是对的。它不接受string_view
。然而,似乎 OP 尝试使用 string_view
而不是字符串的唯一原因是出于效率考虑,在他的特殊情况下,按值传递的常规字符串似乎是更好的选择。
如果确实需要,也可以添加一个采用 string_view
的构造函数
@M.M 它不起作用,因为const char*
转换变得模棱两可。这就是为什么我不喜欢 clang-tidy 在这种情况下建议的原因 - 唯一“有效”的方法是提供 3 个重载:const char *
、std::string_view
和 std::string&&
。以上是关于在这种情况下,使用 string_view 会导致不必要的字符串复制吗?的主要内容,如果未能解决你的问题,请参考以下文章