英文:
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 = "abc";
std::string_view strV = str;
std::cout << strV << std::endl;
str = "1";
std::cout << strV << 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论