|
|
|
@ -324,17 +324,17 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
一旦创建了 `leaf`,其 `Rc<Node>` 的强引用计数为 1,弱引用计数为 0。在内部作用域中创建了 `branch` 并与 `leaf` 相关联,此时 `branch` 中 `Rc<Node>` 的强引用计数为 1,弱引用计数为 1(因为 `leaf.parent` 通过 `Weak<Node>` 指向 `branch`)。这里 `leaf` 的强引用计数为 2,因为现在 `branch` 的 `branch.children` 中储存了 `leaf` 的 `Rc<Node>` 的拷贝,不过弱引用计数仍然为 0。
|
|
|
|
|
|
|
|
|
|
当内部作用域结束时,`branch` 离开作用域,`Rc<Node>` 的强引用计数减少为 0,所以其 `Node` 被丢弃。来自 `leaf.parent` 的弱引用计数 1 与 `Node` 是否被丢弃无关,所以并没有产生任何内存泄露!
|
|
|
|
|
当内部作用域结束时,`branch` 离开作用域,`Rc<Node>` 的强引用计数减少为 0,所以其 `Node` 被丢弃。来自 `leaf.parent` 的弱引用计数 1 与 `Node` 是否被丢弃无关,所以并没有产生任何内存泄漏!
|
|
|
|
|
|
|
|
|
|
如果在内部作用域结束后尝试访问 `leaf` 的父节点,会再次得到 `None`。在程序的结尾,`leaf` 中 `Rc<Node>` 的强引用计数为 1,弱引用计数为 0,因为现在 `leaf` 又是 `Rc<Node>` 唯一的引用了。
|
|
|
|
|
|
|
|
|
|
所有这些管理计数和值的逻辑都内建于 `Rc<T>` 和 `Weak<T>` 以及它们的 `Drop` trait 实现中。通过在 `Node` 定义中指定从子节点到父节点的关系为一个`Weak<T>`引用,就能够拥有父节点和子节点之间的双向引用而不会造成引用循环和内存泄露。
|
|
|
|
|
所有这些管理计数和值的逻辑都内建于 `Rc<T>` 和 `Weak<T>` 以及它们的 `Drop` trait 实现中。通过在 `Node` 定义中指定从子节点到父节点的关系为一个`Weak<T>`引用,就能够拥有父节点和子节点之间的双向引用而不会造成引用循环和内存泄漏。
|
|
|
|
|
|
|
|
|
|
## 总结
|
|
|
|
|
|
|
|
|
|
这一章涵盖了如何使用智能指针来做出不同于 Rust 常规引用默认所提供的保证与取舍。`Box<T>` 有一个已知的大小并指向分配在堆上的数据。`Rc<T>` 记录了堆上数据的引用数量以便可以拥有多个所有者。`RefCell<T>` 和其内部可变性提供了一个可以用于当需要不可变类型但是需要改变其内部值能力的类型,并在运行时而不是编译时检查借用规则。
|
|
|
|
|
|
|
|
|
|
我们还介绍了提供了很多智能指针功能的 trait `Deref` 和 `Drop`。同时探索了会造成内存泄露的引用循环,以及如何使用 `Weak<T>` 来避免它们。
|
|
|
|
|
我们还介绍了提供了很多智能指针功能的 trait `Deref` 和 `Drop`。同时探索了会造成内存泄漏的引用循环,以及如何使用 `Weak<T>` 来避免它们。
|
|
|
|
|
|
|
|
|
|
如果本章内容引起了你的兴趣并希望现在就实现你自己的智能指针的话,请阅读 [“The Rustonomicon”][nomicon] 来获取更多有用的信息。
|
|
|
|
|
|
|
|
|
|