15

我发现来自新 C++17 标准的 string_view 有点多余。

我们有一个非常冗长的简单机制集合,用于将数据传递给被调用者,没有太多开销,现在还有一个也只针对一种容器类型。

我不明白为什么只为字符串提供这种机器,而不是为其他容器提供一些更通用的类型。一个明智的答案是我们已经有了这些解决方案。例如,在C++17 及以后的演示文稿中,string_view 被解释为observer_ptr<T> (or T*) for string.

请针对更通用的 container_view 陈述论点,与 C++17 引入的 string_view 形成对比。

4

2 回答 2

14

广义container_view的更恰当地称为范围。我们有一个完全致力于范围概念的 TS 航路。

现在,我们有string_view一个单独的类型,因为它有一个专门的、特定于字符串的接口来匹配特定于basic_string字符串的接口。或者至少,匹配 const/非分配接口。

请注意,container_view无论您如何称呼它,它都无法删除它与生成它的容器的连接。或者至少,在每次访问/操作上都需要支付类型擦除开销。

相比之下,string_view是基于const char*s 和整数的。该类不关心字符串来自何处;无论谁拥有它,它都可以查看连续的字符数组。它可以这样做,因为它知道源是一个连续的数组,因此使用指针作为其迭代器的核心。

您不能对任意容器执行此操作。你container_view<vector>会有不同的迭代器container_view<list>或其他。它必须。这意味着如果您将 acontainer_view作为函数参数,则必须选择要使用的特定容器(强制用户准确提供该容器类型),使您的函数成为模板,或使用类型擦除的迭代器范围(因此速度较慢)。

还有针对 GSL 类型spanmdspan. 前者表示连续数组的可修改“视图”。后者表示您视为多维的连续数组的可修改“视图”。

于 2016-08-19T13:30:27.873 回答
4

string_view提供的不仅仅是一个简单的字符串指针。您需要将其视为不仅仅是一个简单的非拥有指针:如果仅此而已,则string_view不能允许您“切片”字符串的一部分并对它应用操作(同时仍然是一个视图;因此不是产生复制费用):

char *s = "welcome to stackoverflow";
auto s = std::string_view{s + 8, 2}; // a view on "to"
// you can then apply many operations on this view, that wouldn't make sense more on your general non_owning<T>:
s.remove_prefix(std::min(s.find_first_not_of(" "), s.size()));
// it also "inherits" (copies the API) a lot directly from std::basic_string
auto view2 = s.substr(3, 4); // a generic non-owning ptr would copy here, instead of giving you a new view
于 2016-08-19T08:32:48.777 回答