我正在通过一本书学习Rust,下面的摘录让我有点失望:
另请注意,
&str
前面有 &
,因为您需要参考才能使用 str
。这是因为我们上面看到的原因:堆栈需要知道大小,并且 str
可以是任意长度。所以我们通过引用 &
来访问它。编译器知道引用指针的大小,然后可以使用 &
查找 str
数据所在的位置并读取它。此外,由于您使用 &
与 str
进行交互,因此您并不拥有它。但 String
是“拥有”类型。
我的理解是,对于未知大小的变量,必须将数据放在堆上,然后在栈上用定长指针来引用它。我的困惑在于
str
可以是任意长度。
为什么
String
类型有时不能具有未知长度并需要对堆方法中的数据进行完整引用?
我知道这本书稍后可能会更深入地探讨细节,但我想知道是否有人可以为我提供一些额外的背景信息,特别是关于上面的问题?关于
Rust中的
&str
和 String
类型的任何有用的附带详细信息,对于该语言的初学者来说是很好的了解,也受到高度赞赏。
就像切片
[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
等效项在堆栈上分配可变大小的数据。