我可以改变一个已经分配给std::string_view的std::string吗?

huangapple go评论47阅读模式
英文:

Can I change a std::string, which has been assigned to a std::string_view

问题

我刚刚得知C++17引入了std::string_view。它不持有任何字符串,而是指向一个字符串。如果是这样的话,我对下面的情况感到困惑:

std::string str = "abc";
std::string_view strV = str;
std::cout << strV << std::endl;
str = "1";
std::cout << strV << std::endl;

我刚刚在一些在线C++17编译器上尝试了这段代码,以下是输出:

abc
1c

显然,1c不是我预期的结果。

所以这是否意味着我们不应该更改已分配给std::string_view的字符串?

英文:

I just knew that C++17 introduced std::string_view. It doesn't hold any string, instead, it points to a string. If so, I'm confused by the case below:

std::string str = &quot;abc&quot;;
std::string_view strV = str;
std::cout &lt;&lt; strV &lt;&lt; std::endl;
str = &quot;1&quot;;
std::cout &lt;&lt; strV &lt;&lt; std::endl;

I just tried the piece of code on some c++17 compiler online, here is the output:

abc
1c

Obviously, 1c is not what I expected.

So does it mean that we shouldn't change the string which has been assigned to a std::string_view?

答案1

得分: 7

通常情况下,你不应该这样做,因为它是脆弱的。
无论如何:

你可以改变引用后面的数据(std::string_view 是对字符串片段的引用,而不是像 std::string 一样对整个字符串的引用,它由起始位置和长度组成),只要意识到你这样做了以及如何做的就可以了。
尽量避免释放它,使用悬挂引用是不好的。

如果新值适合当前容量并且没有移动赋值,或者两者都处于SBO模式,std::string 就不会重新分配内存。
在你的示例中,这三个条件都成立。

唯一的问题是,在赋值之后,字符串终止符后面的数据是不确定的,尽管它没有被明确覆盖,因此保持了c以提高效率。

英文:

In general, you shouldn't, as it is fragile.
Anyway:

You may change the data behind a reference (a std::string_view is a reference to a string-segment, not to a string like std::string, consisting of start and length), just be aware that you did and how you did it.
Though refrain from deallocating it, using dangling references is bad.

std::string doesn't reallocate if the new value fits the current capacity and there is no move-assignment, or both are in SBO-mode.
In your example, all three are true.

The only problem is that the data beyond the string-terminator is indeterminate after the assignment, though it is not explicitly overwritten, thus staying c for efficiency.

答案2

得分: 6

一个 string_view 存储了指向字符串开头的指针以及字符串的长度。替换 string 中存储的文本会使它们都失效,因为这可能导致不同的长度和/或不同的存储位置。

所以是的,改变字符串会使 string_view 失效。

英文:

A string_view stores a pointer to the start of the string and the length of the string.
Replacing the text stored by the string invalidates both of them, since this might lead to a different length and/or a different storage location.

So yes changing the string invalidates the string_view.

答案3

得分: 3

std::string_view 只是对包含字符的缓冲区的常量引用的一种高级形式。这个缓冲区可以由 std::string 管理,也可以是字符串字面量或一些 char 数组。

因此,使用 std::string_view 不得超出此缓冲区的生存周期。在您的示例中,在使用字符串视图之前修改了缓冲区,导致未定义的行为。

现在由于大多数编译器正在实施小字符串优化,您的示例没有崩溃。在更一般的情况下,这段代码将失败。

请注意,std::string_view 主要是为了更有效地解析未修改的长字符串中的某些数据而引入的。

英文:

std::string_view is just fancy form of const reference to buffer containing characters. This buffer can be manged by std::string or can be string literal or some array of char.

As a result use of std::string_view must not extend beyond of lifetime of this buffer. In your example buffer was modified before string view was used leading to undefined behavior.

Now since most compilers are implementing Small String Optimization, your example didn't crash. In more general cases this code will fail miserably.

Note that std::string_view was introduced mainly to more effectively parse some data in long strings which are not modified.

huangapple
  • 本文由 发表于 2023年6月26日 17:51:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76555533.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定