Update Ch15

This commit is contained in:
Unisko PENG 2023-05-08 16:35:53 +08:00
parent 479e33d411
commit d028894823

View File

@ -383,17 +383,17 @@ impl<T> Deref for MyBox<T> {
我们在 `deref` 方法的主体中填入 `&self.0`,这样 `deref` 就会返回一个我们想用 `*` 操作符访问的值的引用;回顾一下第五章 [“使用没有命名字段的元组结构体来创建不同的类型”](Ch05_Using_Structs_to_Structure_Related_Data.md#使用没有命名字段的元组结构体来创建不同的类型) 小节,`.0` 可以访问一个元组结构体中的第一个值。清单 15-9 中调用 `MyBox<T>` 值的 `main` 函数现在可以编译了,而且断言也通过了!
没有这个 `Deref` 特质,编译器就只能解引用那些 `&` 的引用。那个 `deref` 方法,给到了编译器取得实现了 `Deref` 特质的任意类型值的能力,而调用该特质的 `deref` 方法,就获得了其知道如何解引用的一个 `&` 引用。
如果没有 `Deref` 特质,编译器只能对 `&` 引用进行解引用。`deref` 方法给了编译器这样的能力:取一个实现 `Deref` 的任何类型的值,并调用 `deref` 方法来获得一个他知道如何解除引用的 `&` 引用。
在于清单 15-9 中敲入 `*y` 时,在幕后 Rust 实际上运行了下面的代码:
当我们在清单 `15-9` 中输入 `*y` 时,在幕后 Rust 实际上运行了下面这段代码:
```rust
*(y.deref())
```
Rust 使用到 `deref` 方法的一个调用,以及接着一个普通的解引用,替换了那个 `*` 运算符,如此咱们就不必考虑,这里到底需不需要调用那个 `deref` 方法了。Rust 的这项特性,实现了不论对于常规引用,或是对实现了 `Deref` 特质的类型,以同样方式起作用代码的编写
Rust `*` 运算符替换为对 `deref` 方法的调用,然后是普通的解引用,这样咱们就不必考虑是否需要调用 `deref` 方法。这个 Rust 特性让我们可以编写功能相同的代码,无论我们有一个常规引用还是一个实现了 `Deref` 的类型
那个`deref` 返回到某个值的引用,以及 `*(y.deref())` 中括号外的那个普通解引用,二者都有其存在的必要原因,那就是配合了 Rust 的所有权系统。假如这个 `deref` 方法直接返回值,而不是到值的引用,那么该值就会被迁移出 `self`。咱们并未打算取得这个示例,或用到解引用操作符的其他绝大多数用例中,`MyBox<T>` 里头那个内层值的所有权。
`deref` 方法返回一个值的引用,以及 `*(y.deref())` 中括号外的普通解引用仍然是必要的,其原因与所有权系统有关。如果 `deref` 方法直接返回值,而不是返回值的引用,值就会被移出 `self`。在这种情况下,或者在大多数使用解引用操作符的情况下,我们不希望取得 `MyBox<T>` 内部的值的所有权。
请注意那个 `*` 运算符被替换为了到 `deref` 方法的一次调用,和随后到 `*` 运算符的一次调用,这替换只有一次,且咱们在代码中用到一次 `*` 运算符,这种替换就会进行一次。由于 `*` 运算符的这种替代不会无限递归,因此这里就会以类型 `i32` 的数据而结束,其正好与清单 15-9 中那个 `assert_eq!` 里的 `5` 匹配。