4

这些方法的实现对我来说似乎很简单,它们可以使用std::string并且std::string_view更具可互换性。毕竟,std::string_view有构造函数使对象处于与这些方法相同的状态。可以解决这样的缺失方法:

std::string s {"abcd"};
std::string_view v {s.c_str()};
std::cout << "ctor:   " << v << std::endl; // "abcd"
v = {s.c_str() + 1, 2};
std::cout << "assign: " << v << std::endl; // "bc"
v = {nullptr}; // or even v = {};
std::cout << "clear:  " << v << std::endl; // ""

那么,标准中没有包括这两种明显的方法的原因是什么?

更新:您评论中的一个普遍问题似乎是“有什么意义?”,所以我会给您一些背景信息。我正在解析一个大字符串,结果是子字符串的结构。该结果结构是字符串视图的自然候选者,因此我不必复制所有那些甚至重叠的字符串。结果的一部分是到字符串视图的映射,因此我可能需要在获取键时将它们构造为空,并在稍后获取值时填充它们。在解析时,我需要跟踪中间字符串,这涉及更新和重置它们。现在它们也可以被字符串视图替换,这就是我在那些缺失的函数上发生的事情。当然,我可以继续使用字符串或用普通的旧 ptr-ptr 或 ptr-size 对替换它们,但这正是std::string_view它的用途,

4

5 回答 5

5

std::string接口因其糟糕的API而声名狼藉,这就是为什么std::string_view不太可能std::string仅仅因为它方便或使两种类型更易于互换而获得尽可能多的方法。

但更重要的是,这些类型并不意味着可以互换。“清除”字符容器上的视图是什么意思?正如clear()所有 STL 容器上都存在并做一些有意义的事情一样,拥有 astd::string_view::clear()会很令人困惑。

此外,某些数据的视图是为了临时使用,例如只读函数参数。你为什么要分配给它呢?这是一个示例函数签名,它使用std::string_view

// Called e.g. with "x86_64-Darwin-16.7.0"
std::string_view extractOSName(std::string_view configStr)
{
    // Parse input, return a new view. Lifetime/ownership managed by caller.
    // No need to re-assign anything, let alone "clearing" them.
}
于 2019-01-24T12:02:42.347 回答
3

这只是真正的猜测,但普遍的共识似乎是这些操作将是中等程度的不清楚。

就我个人而言,我认为“清除视图”是完全有道理的(我们也不要忘记这一点remove_prefixremove_suffix存在!虽然见下文......),但我也同意还有其他解释,这可能很常见,但意义不大。回想一下,string_view它旨在补充const std::string&,而不是std::string,并且您命名的函数都不是std::string的常量接口的一部分。

老实说,我们完全需要这种对话的事实本身可能是一个很好的理由,一开始就没有这个功能。

的最终提案string_view来看,以下段落不是关于assignclear具体的,而是作为委员会对此主题的相关观点[lol] :

s/remove_prefix/pop_front/, etc.

在 Kona 2012 中,我提出了一个range<>包含pop_front, etc. 成员的类来调整范围的边界。那里的讨论表明,委员会成员对使用与集装箱操作相同的名称来表示轻型靶场操作感到不舒服。现有做法不同意此操作的名称,因此我保留了 Google 的StringPiece.

该提案实际上确实包括了一个,它在后来的一个孤立的、缺乏理由的提案clear()中被毫不客气地从登记册中删除。

现在,有人可能会争辩说,这些功能因此可以以不同的名称提供,但这从未被提出过,而且很难想象有哪些替代名称可以解决这个问题,而不仅仅是操作的坏名称。

因为我们可以很容易地分配一个新string_view的,包括一个空的,所以整个问题都可以通过简单地解决它来解决。

于 2019-01-24T15:19:50.130 回答
2

这些方法的实现对我来说似乎很简单,它们可以使用std::string并且std::string_view更具可互换性。

std::string_view并非旨在替代std::string. 它旨在替代const std::string&. assign并且clear不是const std::string&您可以调用的成员函数。

于 2019-01-24T15:19:28.683 回答
0

string_view当后备存储不在您的控制范围内时,可能是纯 C 字符串(数组)的出色字符串接口包装器char,但是您仍然希望访问/修改内容而没有能力(或不需要)干预后备存储(即在动态内存分配没有问题的情况下)。

于 2021-09-30T11:37:56.970 回答
0

std::string_views 是对内存中其他地方的字符串的引用。但与好的(或坏的)旧 C 不同char *std::string_views 有一个指针和一个大小。这就是为什么它们可以引用其他字符串的特定部分,这就是为什么对 sremove_prefix()进行remove_suffix()有意义的操作string_view

但是,您不需要 for 的assign()方法std::string_view,因为这与赋值运算符没有什么不同。std::string有一种assign()方法可以处理很多情况,赋值运算符std::string无法处理,因为它不能接受多个参数。几个例子:

std::string A { "This is a somewhat lengthy string" };
std::list<char> L { '1', 'A', 'Z' };
std::string B;

B.assign(80, ' ');               // Create an empty line of spaces
B.assign(A, 10, 8);              // Copy out a substring of another string
B.assign(L.begin(), L.end());    // Assign from an STL container

在这三种情况中,只有中间一种对 有意义std::string_view。第一种和最后一种情况都需要分配一个字符串,这是std::string_view不能做的。

然而,中间的情况可以很容易地通过使用来实现std::string_view::substr()。例如:

std::string A { "This is a somewhat lengthy string" };
std::string_view V { "Directly pointing to A C string" };
std::string_view B;

B = std::string_view{A}.substr(10, 8);    // Reference substring of A
B = B.substr(0, 4);                       // Further shorten the reference
B = V.substr(0, 8);                       // Reassign with another reference
B = B.substr(0, 0);                       // "Clear" the string_view

因此,clear()assign()to astd::string_view都可以使用赋值运算符来完成。这不适用于std::string: 中间分配用来自 的数据B.assign(A, 10, 8);覆盖已经分配B的数据A。使用赋值运算符 like 的解决方案B = A.substr(10, 8);将导致std::string通过substr()调用创建一个临时对象,然后内部释放B之前分配的内存。这通常效率不高,这就是将子字符串分配方法添加到std::string(). 另一方面,std::string_view::substr()不需要复制任何字符串数据,因此B = std::string_view{A}.substr(10, 8);可以轻松优化分配!

请注意,以下代码是一个错误,并且会在堆上留下对临时子字符串的悬空引用:

std::string A { "This is a somewhat lengthy string" };
std::string_view V { A.substr(10, 8) };

因此,如果您需要将 a 设置std::string_view为字符串的子字符串,请始终转换为std::string_view第一个(通过std::string_view(string)),然后substr()std::string_view. 当然,请确保原始string文件比新生成的文件更有效std::string_view,否则您最终会得到悬空引用。

于 2021-10-13T09:31:02.377 回答