Update Ch15

This commit is contained in:
Unisko PENG 2023-05-11 08:45:08 +08:00
parent b539031b11
commit 426a335ec1

View File

@ -774,13 +774,14 @@ $ cargo run
- 在任何给定时间,咱们都可以有着 *要么* (而非同时) 一个可变引用,要么任意数量的不可变引用;
- 引用必须始终有效。
在引用及 `Box<T>` 之下这些借用规则的那些不变性在编译时被强制检查with references and `Box<T>`, the borrowing rules' invariants are enforced at compile time。而在 `RefCell<T>` 之下,这些不变性是在 *运行时runtime*,被强制检查的。对于引用,在破坏这些规则时,就会得到编译时错误。而对于 `RecCell<T>`,在破坏这些规则时,程序就会终止运行并退出。
在编译时检查借用规则的好处,就是那些错误会在开发过程中被及时捕获到,而因为全部代码分析都是提前完成的,因此在运行时性能上没有影响。由于这些原因,在编译时检查借用规则,即是大多数情形中的最佳实践,也正是 Rust 作为默认项的原因
对于引用与 `Box<T>`借用规则的不变性the borrowing rules' invariants, 是在编译时强制执行的。对于 `RefCell<T>`,这些不变性则是在运行时强制执行的。对于引用,如果咱们破坏了这些规则,咱们会得到编译器报错。而在 `RefCell<T>` 中,如果咱们破坏了这些规则,咱们的程序将终止运行
相反在运行时检查借用规则的优势,在于这个时候明确的内存安全场景是被允许的,这些场景中,他们原本是不被编译时借用规则检查所允许。一些静态分析,好比 Rust 的编译器本质上是保守的。代码的一些属性都是不可能通过分析代码侦测到的其中最有名的示例便是图灵停机问题the Halting Problem这个问题超出了本书的范围但是个要研究的有趣话题
在编译时检查借用规则的好处是在开发过程中会更早地发现错误,而且对运行时性能没有影响,因为所有分析都是事先完成的。由于这些原因,在大多数情况下,在编译时检查借用规则是最好的选择,这就是为什么这是 Rust 的默认设置
由于某些分析不可能进行,因此在 Rust 编译器无法确定代码,在所有权规则下会编译时,他就会拒绝某个正确的程序;从这方面讲,他就是保守的了。假如 Rust 编译器接受不正确的程序,那么用户将无法信任 Rust 所做出的那些保证。然而,若 Rust 拒绝某个正确程序,那么编程者就将感到不便,却又不会发生什么灾难性的事情。在咱们确定咱们的代码遵循了借用规则,只不过编译器无法理解并确保那一点时,`RefCell<T>` 类型便是有用的了。
相反,在运行时检查借用规则的优点是允许某些内存安全的场景,而编译时检查则不会允许这些场景。与 Rust 编译器一样静态分析static analysis本质上是保守的。代码的某些属性无法通过分析代码来检测最著名的例子是停机问题the Halting Problem, 它超出了本书的范围,但却是一个值得研究的有趣主题。
由于某些分析是不可行的,那么如果 Rust 编译器不能确定代码符合所有权规则,他可能会拒绝某个正确的程序;从这方面讲,他是保守的。如果 Rust 编译器接受了错误的程序,用户就无法相信 Rust 做出的保证。然而,如果 Rust 拒绝了某个正确的程序,编程者会感到不便,但又不会发生什么灾难性的事情。在咱们确定咱们的代码遵循借用规则,而编译器无法理解和保证时,`RefCell<T>` 类型就很有用。
`Rc<T>` 类似,`RefCell<T>` 仅用于一些单线程场景中,并在咱们尝试将其用于多线程语境中时,将给到一个编译时报错。在第 16 章将讲到怎样在多线程的程序中,获得 `RefCell<T>` 的功能。