我在一本书上学习 Rust,下面的摘录让我有点困惑:
- 还要注意,
&str
前面有&
,因为你需要一个引用来使用str
。这是因为我们上面看到的原因:堆栈需要知道大小,str
可以是任何长度。所以我们用&
,一个引用来访问它。编译器知道引用指针的大小,然后它可以使用&
来查找str
数据的位置并读取它。此外,因为您使用&
与str
交互,所以您不拥有它。但是String
是一个“拥有”类型。
我知道对于未知大小的变量,你必须把数据放在堆上,然后在栈上用一个固定长度的指针引用它。我的困惑在于声明**str
可以是任何长度**。
为什么String
类型不能有时也是未知长度,并要求整个引用堆方法上的数据?
我知道这本书可能会在后面更深入地探讨细节,但我想知道是否有人已经为我提供了一些额外的背景,特别是关于上面的问题?关于 Rust 中&str
和String
类型的任何有用的附带细节,对于语言初学者来说是很好的,也非常感谢。
1条答案
按热度按时间6pp0gazn1#
与分片
[T]
一样,str
也是一个可变大小的类型(事实上,str
本质上是一个[u8]
,保证包含有效的UTF-8)。可变大小的类型是特殊的,它们不实现
Sized
特征。对可变大小类型的引用是“胖的”:它不仅保存被引用对象的地址,还保存其大小。因此,
str
表示“内存中包含有效UTF-8数据的某个区域”,而&str
则是“该区域的地址和大小”。另一方面,
String
是一个固定大小的结构体,它的一个成员是指向其他地方的字符串数据的指针(在堆上)。从概念上讲,String
* 包含 *&str
沿着内存区域的未使用容量。(实际上,String
是Vec<u8>
的 Package 器,具有UTF-8保证,而Vec<u8>
概念上包含&[u8]
和容量,但实际上是原始指针、大小和容量。)因此,
String
所需的总内存仍然是可变的,但String
结构本身的部分是已知的。为什么会这样呢?因为
String
的全部目的是 * 管理 * 包含字符串数据的内存区域,而如果它是 * 包含字符串数据的内存区域,它就不能这样做。一个旁白:
我知道,对于未知大小的变量,必须将数据放在堆上
这是一个误解。堆是最明显的放置可变大小数据的地方,但是
alloca
等效项在堆栈上分配大小可变的数据。