Rust 中切片和引用之间的关系是什么?

ge9*_*7aa 6 string reference slice rust

我对 Rust 完全陌生(就像我昨天才开始研究它一样),并且正在研究“Rust 编程语言”。我对第 4.2 章(参考文献和借用)/4.3(切片类型)有点卡住,在继续之前,我试图巩固我对参考文献的初步理解。我是一位经验丰富的程序员,背景主要是 C++(我非常熟悉多种语言,但 C++ 是我最熟悉的)。

考虑以下 Rust 代码:

let string_obj: String = String::from("My String");
let string_ref: &String = &string_obj;
let string_slice: &str = &string_obj[1..=5];
Run Code Online (Sandbox Code Playgroud)

根据我的理解,从第一行开始,是一个存储在堆栈上的string_obj类型的对象,它包含三个字段:(1)指向文本“My String”的指针,分配在堆上,以UTF-8编码String; (2)长度字段,值为9;(3) 容量字段的值 >= 9。这很简单。

第二行string_ref是对对象的不可变引用String,也存储在堆栈上,其中包含单个字段 - 指向 的指针string_obj。这让我相信(抛开所有权规则、语义以及我尚未了解的有关引用的其他内容),引用本质上是指向其他对象的指针。再说一次,非常简单。

这是第三行,让我有些头疼。从文档中可以看出,它string_slice是一个存储在堆栈上的类型的对象&str,并且包含两个字段:1)指向与 关联的文本“My String”内的文本“y Str”的指针string_obj。2) 长度字段值为 5。

但是,至少从表面上看,该&str类型根据定义是对类型对象的不可变引用str。所以我的问题如下:

  1. an到底str什么,它在内存中是如何表示的?
  2. 认为引用&str类型只是一个指针,它如何包含两个字段(一个指针和一个长度)?
  3. Rust 通常如何知道在构造引用时要创建哪些/多少个字段?(那么程序员怎么知道呢?)

cdh*_*wie 8

切片是Rust 中的原始类型,这意味着它们不一定必须遵循其他类型的语法规则。在这种情况下,str&str是特殊的并且被施以一些魔法。

该类型str并不真正存在,因为您不能拥有拥有其内容的切片。要求我们拼写这种类型“ &str”的原因是语法上的:它&提醒我们正在使用从其他地方借来的数据,并且需要能够指定生命周期,例如:

fn example<'a>(x: &String, y: &'a String) -> &'a str {
    &y[..]
}
Run Code Online (Sandbox Code Playgroud)

这也是必要的,以便我们可以区分不可变借用的字符串切片 ( &str) 和可变借用的字符串切片 ( &mut str)。(尽管后者的用处有些有限,因此您不会经常看到它们。)

请注意,同样的情况也适用于数组切片。我们有像这样的数组[u8; 16],也有像这样的切片&[u8],但我们并没有真正直接与 交互[u8]。这里的可变变体 ( &mut [u8]) 比字符串切片更有用。

an到底str什么,它在内存中是如何表示的?

如上所述,strkind-of 本身并不真正存在。其布局&str正如您所怀疑的那样——一个指针和一个长度。

(str是切片引用的实际字符,是所谓的动态大小类型。一般情况下,&T如果没有 a 引用,则 a 不可能存在T。在这种情况下,它有点倒退,因为 astr不存在'没有切片就不存在&str。)

认为引用&str类型只是一个指针,它如何包含两个字段(一个指针和一个长度)?

作为原语,它是编译器处理的特殊情况。

Rust 通常如何知道在构造引用时要创建哪些/多少个字段?(那么程序员怎么知道呢?)

如果它是非切片引用,那么它要么是指针,要么什么都不是(如果可以优化引用本身)。