rust 为什么str类型可以是任意大小(未知大小),而String类型的大小应该是已知的?

rxztt3cl  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(118)

我在一本书上学习 Rust,下面的摘录让我有点困惑:

  • 还要注意,&str前面有&,因为你需要一个引用来使用str。这是因为我们上面看到的原因:堆栈需要知道大小,str可以是任何长度。所以我们用&,一个引用来访问它。编译器知道引用指针的大小,然后它可以使用&来查找str数据的位置并读取它。此外,因为您使用&str交互,所以您不拥有它。但是String是一个“拥有”类型。

我知道对于未知大小的变量,你必须把数据放在堆上,然后在栈上用一个固定长度的指针引用它。我的困惑在于声明**str可以是任何长度**。

为什么String类型不能有时也是未知长度,并要求整个引用堆方法上的数据?

我知道这本书可能会在后面更深入地探讨细节,但我想知道是否有人已经为我提供了一些额外的背景,特别是关于上面的问题?关于 Rust&strString类型的任何有用的附带细节,对于语言初学者来说是很好的,也非常感谢。

6pp0gazn

6pp0gazn1#

与分片[T]一样,str也是一个可变大小的类型(事实上,str本质上是一个[u8],保证包含有效的UTF-8)。
可变大小的类型是特殊的,它们不实现Sized特征。对可变大小类型的引用是“胖的”:它不仅保存被引用对象的地址,还保存其大小。
因此,str表示“内存中包含有效UTF-8数据的某个区域”,而&str则是“该区域的地址和大小”。
另一方面,String是一个固定大小的结构体,它的一个成员是指向其他地方的字符串数据的指针(在堆上)。从概念上讲,String * 包含 * &str沿着内存区域的未使用容量。(实际上,StringVec<u8>的 Package 器,具有UTF-8保证,而Vec<u8>概念上包含&[u8]和容量,但实际上是原始指针、大小和容量。)
因此,String所需的总内存仍然是可变的,但String结构本身的部分是已知的。
为什么会这样呢?因为String的全部目的是 * 管理 * 包含字符串数据的内存区域,而如果它是 * 包含字符串数据的内存区域,它就不能这样做。
一个旁白:
我知道,对于未知大小的变量,必须将数据放在堆上
这是一个误解。堆是最明显的放置可变大小数据的地方,但是

  • 字符串文字被放置在只读存储器中,
  • 您可以在某个地方(全局变量、局部堆栈数组)设置一个固定大小的缓冲区,
  • 低级别,您可以使用某些alloca等效项在堆栈上分配大小可变的数据。

相关问题