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

标签 string rust reference slice

我对 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];

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

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

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

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

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

最佳答案

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

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

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

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

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

What exactly is an str, and how is it represented in memory?

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

(str 是 slice 引用的实际字符,也就是所谓的 dynamically-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?)

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

关于string - Rust 中的切片和引用之间的关系是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71516959/

相关文章:

Java 的速度几乎是 Rust 的两倍?!?我错过了什么?

winapi - 找不到 "wincontypes"

c++ - 使用行为不同的引用返回 tmp

c# - 除了 System.OutOfMemoryException 之外,string = string 还会抛出哪些异常?

javascript - 如何在每个随机生成的字符串 Javascript 中添加公共(public)字符串

java - 通用分词器

rust - 包含一段数据和被引用数据的结构中的生命周期

Java - 即时改变倒数计时器的速度

sql - 标准的SQL关键字?

javascript - 如何在文本文件中的两个句子之间找到特定的单词