Update Ch15

This commit is contained in:
Peng Hailin, 2023-05-07 15:17:25 +08:00
parent 4f9e10c765
commit 123938569a

View File

@ -132,11 +132,11 @@ error: could not compile `sp_demos` due to previous error
*清单 15-4在尝试定义递归枚举时咱们得到的报错*
报错显示此类型“具有无限大小has infinite size”。该错误指出这个类型 “有着无穷大小has infinite size。”原因在于这里已把 `List` 定义为了有着一个递归的变种其直接拥有其自身类型的另一个值。如此一来Rust 就无法找出他需要多少空间来存储一个 `List` 类型值。接下来就要深究收到这个错误的原因。首先这里将审视一下Rust 是怎样确定出,他需要多少内存空间来存储某个非递归类型值。
报错显示此类型“具有无限大小has infinite size”。原因是咱们一个递归的变种定义了 `List`其直接持有自己的的另一个值。因此Rust 无法计算出他需要多少空间来存储一个 `List` 值。咱们来分析一下为什么咱们会得到这个报错。首先,咱们来看看 Rust 如何确定出他需要多少内存空间来存储某个非递归类型值。
**计算非递归类型的大小**
#### 计算非递归类型的大小
回顾在第 6 章中讨论枚举的定义时,于清单 6-2 中曾定义的那个 `Message` 枚举:
回顾咱们在第 6 章讨论枚举定义时,在清单 6-2 中定义的 `Message` 枚举:
```rust
enum Message {
@ -147,16 +147,16 @@ enum Message {
}
```
要确定出给一个 `Message` 值分配多少内存空间Rust 就要遍历其中的各个变种以发现哪个变种需要最多的空间。Rust 会发现 `Message::Quit` 无需任何空间,`Message::Move` 需要存储两个 `i32` 值的足够空间,并如此等等。由于只会用到一个变种,因此某个 `Message` 值将需要的最大内存空间,就是他要用于存储其变种中最大的那个
为了确定出给一个 `Message` 值分配多少内存空间Rust 会检查每个变种找出哪个变种需要最多的空间。Rust 发现 `Message::Quit` 不需要任何空间,`Message::Move` 需要存储两个 `i32` 值的足够空间,以此类推。由于只会用到一个变种,因此某个 `Message` 值所需的最大内存空间,便是其存储最大变种的空间
请将这个情况与 Rust 尝试确定出诸如清单 15-2 中, `List` 枚举这种递归类型所需内存空间数量对比。编译器以检视那个保存了一个类型 `i32` 值,与一个类型 `List` 值的 `Cons` 变种开始。那么,`Cons` 就需要等同于一个 `i32` 加一个 `List` 大小数量的内存空间。而要计算出 `List` 类型需要多少内存,编译器就会检视这些变种,以其中的 `Cons` 变种开始。这个 `Cons` 变种保存了一个类型 `i32` 的值,与一个类型 `List` 的值,而这个过程会无限持续,如下图 15-1 中所示。
将此与 Rust 尝试确定递归类型(如清单 15-2 中的 `List` 枚举)需要多少空间时发生的情况进行对比。编译器从查看 `Cons` 变种开始,其持有一个 `i32` 类型的值和一个 `List` 类型的值。因此,`Cons` 需要的空间量等于 `i32` 的大小加上 `List` 的大小。为了计算出 `List` 类型需要多少内存,编译器会从 `Cons` 变体开始查看变种。 `Cons` 变种保存了一个 `i32` 类型的值和一个 `List` 类型的值,这个过程会无限继续下去,如图 15-1 所示。
![由无限的 `Cons` 变种组成的一个无线 `List`](images/15-01.svg)
![由无限的 `Cons` 变种组成的一个无 `List`](images/15-01.svg)
*图 15-01由无限的 `Cons` 变种组成的一个无线 `List`*
*图 15-01由无限的 `Cons` 变种组成的一个无 `List`*
**使用 `Box<T>` 获得一个有着已知大小的递归类型**
#### 使用 `Box<T>` 获得一个有着已知大小的递归类型
由于 Rust 无法计算出,要分配多少内存空间给递归定义的类型,因此编译器就给到有着以下有帮助的一项建议: