Update Ch15

This commit is contained in:
Peng Hailin, 2023-05-07 20:23:00 +08:00
parent 63353ee8e4
commit 00c734fc30
2 changed files with 17 additions and 8 deletions

View File

@ -192,7 +192,7 @@ fn main() {
} }
``` ```
*清单 15-5使用Box<T>的List的定义以便有已知的大小* *清单 15-5使用 `Box<T>` `List` 的定义,以便有已知的大小*
`Cons` 变种需要一个 `i32` 的大小,加上存储匣子指针数据的内存空间。`Nil` 变种不存储存储任何值,所以他需要的空间比 `Cons` 变种少。咱们现在知道,任何 `List` 值都会占用一个 `i32` 的大小,加上一个匣子的指针数据的大小。通过使用匣子,咱们已经破解了无限的递归链,因此编译器可以计算出存储 `List` 值所需的内存大小。下图 15-2 显示了 `Cons` 变种现在的样子: `Cons` 变种需要一个 `i32` 的大小,加上存储匣子指针数据的内存空间。`Nil` 变种不存储存储任何值,所以他需要的空间比 `Cons` 变种少。咱们现在知道,任何 `List` 值都会占用一个 `i32` 的大小,加上一个匣子的指针数据的大小。通过使用匣子,咱们已经破解了无限的递归链,因此编译器可以计算出存储 `List` 值所需的内存大小。下图 15-2 显示了 `Cons` 变种现在的样子:
@ -200,23 +200,23 @@ fn main() {
*图 15-02不在是无限大小的 `List`,因为 `Cons` 持有着一个 `Box`* *图 15-02不在是无限大小的 `List`,因为 `Cons` 持有着一个 `Box`*
匣子数据结构,仅提供了这种间接性的东西与内存堆方面的空间分配;他们不具备像是将在其他灵巧指针类型下,所发现的那些其他特别能力。匣子类型也不会有这些特别能力所招致的性能开销,因此他们在像是构造列表这种,仅需间接性特性的情形下,会是有用的。在第 17 章,还将会检视匣子类型的更多用例。 匣子仅提供这种间接与内存堆的内存分配;他们不具备任何像咱们在其他灵巧指针类型中,将看到的其他特别能力。他们也没有这些特殊能力所带来的性能开销,所以在像构造列表这样的情况下,他们就能很有用,因为间接性是我们唯一需要的功能。在第 17 章,咱们还会看一下匣子的更多用例。
`Box<T>` 类型之所以是灵巧指针,是由于他实现了 `Deref` 特质,这就实现了像引用那样,对待 `Box<T>` 类型的值。在某个 `Box<T>` 值超出作用域时,又由于 `Box<T>` 的那个 `Drop` 实现,那么该匣子所指向的内存堆数据就会被清理。相比本章其余部分将讨论到的由其他灵巧指针所提供到的功能,这两个特质甚至将会更为重要。下面就来更深入地探讨一下这两个特质。 `Box<T>` 类型是一个智能指针,因为他实现了 `Deref` 特质,他允许 `Box<T>` 值被当作引用。当 `Box<T>` 值超出作用域时,由于 `Drop` 特质的实现,匣子所指向的内存堆数据也会被清理。这两个特质对于咱们在本章后面将讨论的其他灵巧指针所提供的功能,将更加重要。咱们来更深入地探讨这两个特质。
## `Deref` 特质下,像常规引用那样看待灵巧指针 ## 使用 `Deref` 特质将智能指针视为常规引用
**Treating Smart Pointers Like Regular References with `Deref` Trait** **Treating Smart Pointers Like Regular References with `Deref` Trait**
那个 `Deref` 特质的实现,就允许咱们,对 *解引用运算符, the dereference operator, *'*' 的行为加以定制(请不要与乘法或全局运算符混淆)。通过以灵巧指针可被像常规引用那样处理这样的方式,实现 `Deref`,咱们就可以编写出运作于引用上的代码,而同时在灵巧指针上使用那些代码 实现 `Deref` 特质允许咱们自定义 *解引用运算符, the dereference operator*'*' (不要与乘法或 glob 运算符相混淆)的行为。通过实现 `Deref`,智能指针可以被当作普通的引用来对待,咱们便可编写对引用进行操作的代码,并将该代码也用于智能指针
接下来首先会看看,这个解引用运算符,是怎样作用于常规引用的。随后咱们就会尝试定义出像 `Box<T>` 那样行事的已知定制类型,而搞清楚为何解引用运算符,不会像在引用上那样,在这个新定义出的类型上起效。这里将探讨怎样实现,这个令到灵巧指针,以类似与引用类似方式运作的 `Deref` 特质。接着这里将看看 Rust 的 *解引用强制* 特性(*deref coercion* feature以及他是怎样实现即工作于引用又工作于灵巧指针之下的。 咱们首先来看看解除引用操作符是如何在常规引用中工作的。然后咱们将尝试定义一个行为类似于 `Box<T>` 的自定义类型,并看看为什么解除引用操作符在咱们新定义的类型上不像引用那样工作。咱们将探讨实现 `Deref` 特性如何使智能指针的工作方式与引用相似。然后咱们将看看 Rust 的 *解引用强制转换deref coercion* 特性,以及其如何让咱们使用引用或智能指针工作的。
> **注意**:在那个即将建立的 `MyBox<T>` 类型与真实的 `Box<T>`Rust 标准库提供的)之间,有着一个大差别:这里的版本并未将其数据存储在内存堆上。由于本小节是着重于 `Deref`,因此相比指针方面行为,数据实际存储于何处则没那么重要 > 注意:咱们将要建立的 `MyBox<T>` 类型和真正的 `Box<T>` 之间有一个很大的区别:咱们的版本不会将其数据存储在堆中。咱们把这个例子的重点放在 `Deref` 上,所以数据实际存储在哪里并不重要,重要的是类似指针的行为
### 跟随指针到其 ### 跟随指针去找
**Following the Pointer to the Value** **Following the Pointer to the Value**

View File

@ -860,6 +860,15 @@ A path dependency
`Box<T>`,由存储在栈上的指针,与存储在堆上的数据,实现的一种数据结构。 `Box<T>`,由存储在栈上的指针,与存储在堆上的数据,实现的一种数据结构。
- 间接
Indirection, 匣子类型的变量,通过保存指向数据在内存堆上的地址,而间接保存了数据。
- 解引用强制转换
Deref coercion类似于其他语言的开箱操作。
- 单态化 - 单态化
所谓 *单态化monomorphization*,是指即通过把在编译后用到的具体类型填入到泛型位置,而将通用代码转换为具体代码的过程。参考 [使用泛型代码的性能问题](Ch10_Generic_Types_Traits_and_Lifetimes.md#使用泛型参数代码的性能问题)。 所谓 *单态化monomorphization*,是指即通过把在编译后用到的具体类型填入到泛型位置,而将通用代码转换为具体代码的过程。参考 [使用泛型代码的性能问题](Ch10_Generic_Types_Traits_and_Lifetimes.md#使用泛型参数代码的性能问题)。