Update Ch15

This commit is contained in:
Unisko PENG 2023-05-15 15:59:31 +08:00
parent ed80d033bf
commit 556af3fe04

View File

@ -1095,11 +1095,11 @@ b 的下一条目 = Some(RefCell { value: Cons(5, RefCell { value: Nil }) })
如果咱们取消对最后一个 `println` 的注释并运行程序Rust 会尝试打印这个循环,`a` 指向 `b` 指向 `a`如此反复直到程序溢出栈overflows the stack。
相较于真实世界的程序,这个示例中创建出循环引用的那些后果并不算非常残酷:在这里创建出那个循环引用之后,这个程序就立马结束了。然而,在更为复杂的程序在某个循环中分配了大量内存,并在其上耗费较长时间时,那么这个程序就会用到相比于其所需要更多的内存,且可能会是系统不堪重负,造成系统耗尽可用内存
与现实世界的程序相比,在这个例子中创建一个引用循环的后果并不可怕:在我们创建引用循环之后,程序就结束了。然而,如果某个更复杂的程序在一个循环中分配了大量的内存,并长期占用这些内存,那么这个程序将使用比其需要的更多的内存,并可能使系统不堪重负,导致其可用内存耗尽
循环引用的创建并非一蹴而就,但也并非是不可能的。在有着包含着 `Rc<T>` 值的一些 `RefCell<T>` 值,或类似的带有内部可变性及引用计数的嵌套类型组合时,咱们就必须确保不会创建出循环引用。咱们不能依靠 Rust 来捕获到循环引用。创建出循环引用来,是属于程序中的逻辑错误,咱们应运用自动化测试、代码审阅,及其他一些软件开发实践来消除
创建引用循环不容易做到,但也不是不可能。如果咱们有着其中包含 `Rc<T>` 值的 `RefCell<T>` 值,或类似的带有内部可变性与引用计数类型的嵌套组合,咱们必须确保不创建循环;咱们不能依靠 Rust 来捕获他们。创建引用循环将是咱们程序中的逻辑错误,咱们应该使用自动测试、代码审查和其他软件开发实践来减少这种错误
避免循环引用的另一种方案,便是重组咱们的数据结构,从而实现一些引用表达所有权,而一些引用则不是。结果就是,咱们是可以有着由一些所有权关系,与一些非所有权关系构成的循环,而只有所有权关系会影响到某个值是否可被丢弃。在清单 15-25 中,咱们是一直要那些 `Cons` 变种拥有他们清单的所有权那么重组其中的数据结构就是不可行的。接下来要看到用到了由一些父节点与子节点组成的图数据结构graphs made up of parent nodes and child nodes的示例来发现在什么时候非所有权关系是防止循环引用的恰当方式。
另一避免引用循环的办法是重新组织咱们的数据结构,使一些引用表达所有权,而一些引用不表达。因此,咱们可以拥有由一些所有权关系和一些非所有权关系组成的循环,而只有所有权关系会影响一个值是否可以被丢弃。在清单 15-25 中,我们总是希望 `Cons` 变体拥有他们的列表,所以重新组织数据结构是不可能的。咱们来看一个使用由父节点和子节点组成的图的示例,看看什么时候非所有权关系是防止引用循环的合适方式。
### 防止引用循环:将 `Rc<T>` 转变为 `Weak<T>`