为什么“str”类型可以是任意大小(未知大小),而“String”类型大小据说是已知的?

问题描述 投票:0回答:1

我正在通过一本书学习Rust,下面的摘录让我有点失望:

另请注意,

&str
前面有
&
,因为您需要参考才能使用
str
。这是因为我们上面看到的原因:堆栈需要知道大小,并且
str
可以是任意长度。所以我们通过引用
&
来访问它。编译器知道引用指针的大小,然后可以使用
&
查找
str
数据所在的位置并读取它。此外,由于您使用
&
str
进行交互,因此您并不拥有它。但
String
是“拥有”类型。

我的理解是,对于未知大小的变量,必须将数据放在堆上,然后在栈上用定长指针来引用它。我的困惑在于

str
可以是任意长度

为什么

String
类型有时不能具有未知长度并需要对堆方法中的数据进行完整引用?

我知道这本书稍后可能会更深入地探讨细节,但我想知道是否有人可以为我提供一些额外的背景信息,特别是关于上面的问题?关于

Rust
中的
&str
String 类型的任何有用的附带详细信息,对于该语言的初学者来说是很好的了解,也受到高度赞赏。

string rust heap-memory
1个回答
4
投票

就像切片

[T]
一样,
str
是一种可变大小的类型。 (事实上,
str
本质上是保证包含有效UTF-8的
[u8]
。)

可变尺寸类型很特殊。他们没有实现

Sized
特征。对可变大小类型的引用是“胖”的:它不仅保存所引用事物的地址,还保存其大小。

因此,

str
的意思是“内存中包含有效 UTF-8 数据的某个区域”。而
&str
就是“这个区域的地址和大小”。


另一方面,

String
是一个具有固定大小的结构体。它的成员之一是指向其他位置(堆上)的字符串数据的指针。从概念上讲,一个
String
包含 一个
&str
以及内存区域未使用的容量。 (实际上,
String
是带有UTF-8保证的
Vec<u8>
的包装,
Vec<u8>
概念上包含
&[u8]
加容量,但实际上是原始指针、大小和容量。)

因此,

String
所需的总内存仍然是可变的,但
String
结构本身的部分是已知的。

为什么会这样?因为

String
的全部意义在于管理包含字符串数据的内存区域,如果它包含字符串数据的内存区域则无法做到这一点。


旁白:

我理解对于未知大小的变量,必须将数据放在堆上

这是一个误解。堆是放置可变大小数据的最明显的地方,但是

  • 字符串文字被放置在只读存储器中,
  • 你可以在某个地方有一个固定大小的缓冲区(全局变量,局部堆栈数组),并在里面放入一些可变大小的数据,只要它适合,
  • 低级,您可以使用一些
    alloca
    等效项在堆栈上分配可变大小的数据。
© www.soinside.com 2019 - 2024. All rights reserved.