Rust 中的切片和引用之间的关系是什么?
What is the relationship between slices and references in Rust?
我对 Rust 完全陌生(因为我昨天才开始研究它),并且正在学习“The Rust Programming Language”。我有点停留在第 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];
根据我的理解,从第一行开始,string_obj
是一个存储在栈中的String
类型的对象,它包含三个字段:(1)指向文本的指针“我的字符串”,分配在堆上,以 UTF-8 编码; (2) 一个值为9的长度字段; (3) 一个容量字段,其值 >= 9。这很简单。
从第二行开始,string_ref
是对 String
对象的不可变引用,它也存储在堆栈中,其中包含一个字段 - 指向 string_obj
的指针。这让我相信(抛开所有权规则、语义和其他我尚未了解的有关引用的内容),引用本质上是指向其他对象的指针。同样,非常简单。
这是让我有些头疼的第三行。从文档中可以看出,string_slice
是存储在堆栈中的 &str
类型的对象,包含两个字段:1) 指向文本“y Str”的指针,在文本中与 string_obj
关联的“我的字符串”。 2) 值为 5 的长度字段。
但是,至少从表面上看,&str
类型根据定义是对类型 str
对象的不可变引用。所以我的问题如下:
- 究竟是什么一个
str
,它在内存中是如何表示的?
- 如何
&str
- reference 类型,我 认为 只是一个指针 - 包含两个字段(一个指针和长度)?
- Rust 通常如何知道在构造引用时要创建什么/多少字段? (因此程序员怎么知道的?)
切片是 Rust 中的原始类型,这意味着它们不一定必须遵循其他类型的语法规则。在这种情况下,str
和 &str
是特殊的,并且经过了一些魔法处理。
str
类型实际上 不存在,因为您不能拥有拥有其内容的切片。要求我们拼写这种类型“&str
”的原因是语法上的:&
提醒我们我们正在处理从其他地方借来的数据, 和 它需要能够指定生命周期,例如:
fn example<'a>(x: &String, y: &'a String) -> &'a str {
&y[..]
}
这也是必要的,这样我们就可以区分 immutably-borrowed 字符串切片 (&str
) 和 mutably-borrowed 字符串切片 (&mut str
)。 (尽管后者的用途有限,因此您不会经常看到它们。)
请注意,同样的事情也适用于数组切片。我们有像 [u8; 16]
这样的数组,我们有像 &[u8]
这样的切片,但我们并没有真正直接与 [u8]
交互。这里的可变变体 (&mut [u8]
) 比字符串切片更有用。
What exactly is an str
, and how is it represented in memory?
如上所述,str
kind-of 本身并不存在。 &str
的布局正如您所怀疑的那样——一个指针和一个长度。
(str
是切片实际引用的字符,是一个so-calleddynamically-sized type。一般情况下,&T
是不存在的没有 T
来引用。在这种情况下它有点倒退,因为没有 &str
切片 str
就不存在。)
How does &str
- a reference type, which I thought was simply a pointer - contain TWO fields (a pointer AND a length)?
作为原语,它是编译器处理的特例。
How does Rust know in general what / how many fields to create when constructing a reference? (and consequently how does the programmer know?)
如果它是一个 non-slice 引用,那么它要么是一个指针,要么什么都不是(如果引用本身可以被优化掉)。
我对 Rust 完全陌生(因为我昨天才开始研究它),并且正在学习“The Rust Programming Language”。我有点停留在第 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];
根据我的理解,从第一行开始,string_obj
是一个存储在栈中的String
类型的对象,它包含三个字段:(1)指向文本的指针“我的字符串”,分配在堆上,以 UTF-8 编码; (2) 一个值为9的长度字段; (3) 一个容量字段,其值 >= 9。这很简单。
从第二行开始,string_ref
是对 String
对象的不可变引用,它也存储在堆栈中,其中包含一个字段 - 指向 string_obj
的指针。这让我相信(抛开所有权规则、语义和其他我尚未了解的有关引用的内容),引用本质上是指向其他对象的指针。同样,非常简单。
这是让我有些头疼的第三行。从文档中可以看出,string_slice
是存储在堆栈中的 &str
类型的对象,包含两个字段:1) 指向文本“y Str”的指针,在文本中与 string_obj
关联的“我的字符串”。 2) 值为 5 的长度字段。
但是,至少从表面上看,&str
类型根据定义是对类型 str
对象的不可变引用。所以我的问题如下:
- 究竟是什么一个
str
,它在内存中是如何表示的? - 如何
&str
- reference 类型,我 认为 只是一个指针 - 包含两个字段(一个指针和长度)? - Rust 通常如何知道在构造引用时要创建什么/多少字段? (因此程序员怎么知道的?)
切片是 Rust 中的原始类型,这意味着它们不一定必须遵循其他类型的语法规则。在这种情况下,str
和 &str
是特殊的,并且经过了一些魔法处理。
str
类型实际上 不存在,因为您不能拥有拥有其内容的切片。要求我们拼写这种类型“&str
”的原因是语法上的:&
提醒我们我们正在处理从其他地方借来的数据, 和 它需要能够指定生命周期,例如:
fn example<'a>(x: &String, y: &'a String) -> &'a str {
&y[..]
}
这也是必要的,这样我们就可以区分 immutably-borrowed 字符串切片 (&str
) 和 mutably-borrowed 字符串切片 (&mut str
)。 (尽管后者的用途有限,因此您不会经常看到它们。)
请注意,同样的事情也适用于数组切片。我们有像 [u8; 16]
这样的数组,我们有像 &[u8]
这样的切片,但我们并没有真正直接与 [u8]
交互。这里的可变变体 (&mut [u8]
) 比字符串切片更有用。
What exactly is an
str
, and how is it represented in memory?
如上所述,str
kind-of 本身并不存在。 &str
的布局正如您所怀疑的那样——一个指针和一个长度。
(str
是切片实际引用的字符,是一个so-calleddynamically-sized type。一般情况下,&T
是不存在的没有 T
来引用。在这种情况下它有点倒退,因为没有 &str
切片 str
就不存在。)
How does
&str
- a reference type, which I thought was simply a pointer - contain TWO fields (a pointer AND a length)?
作为原语,它是编译器处理的特例。
How does Rust know in general what / how many fields to create when constructing a reference? (and consequently how does the programmer know?)
如果它是一个 non-slice 引用,那么它要么是一个指针,要么什么都不是(如果引用本身可以被优化掉)。