From d28696c90ef9fc628f3f41411f47cf31adb55792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A4=E7=8B=90=E4=B8=80=E5=86=B2?= <43949039+anonymousGiga@users.noreply.github.com> Date: Thu, 18 May 2023 10:23:54 +0800 Subject: [PATCH] Update chapter_3_16_7.md --- src/chapter_3/chapter_3_16_7.md | 79 ++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/src/chapter_3/chapter_3_16_7.md b/src/chapter_3/chapter_3_16_7.md index 5260b9d..0c15937 100644 --- a/src/chapter_3/chapter_3_16_7.md +++ b/src/chapter_3/chapter_3_16_7.md @@ -84,4 +84,81 @@ Weak类似于Rc,但它不持有所有权,它仅仅保存一份指向数据 对于上一节中循环链表的例子,使用Weak实现为如下: - +```Rust +use crate::List::{Cons, Nil}; +use std::cell::RefCell; +use std::rc::Rc; +use std::rc::Weak; + +#[derive(Debug)] +enum List { + Cons(i32, RefCell>), + Nil, +} + +impl List { + fn tail(&self) -> Option<&RefCell>> { + match self { + Cons(_, item) => Some(item), + Nil => None, + } + } +} + +fn main() { + let a = Rc::new(Cons(5, RefCell::new(Weak::new()))); + + println!( + "a initial rc count = {}, weak cnt = {}", + Rc::strong_count(&a), + Rc::weak_count(&a) + ); + println!("a next item = {:?}", a.tail()); + + let b = Rc::new(Cons(10, RefCell::new(Weak::new()))); + if let Some(link) = b.tail() { + *link.borrow_mut() = Rc::downgrade(&a); + } + + println!( + "a rc count after b creation = {}, weak cnt = {}", + Rc::strong_count(&a), + Rc::weak_count(&a) + ); + println!( + "b initial rc count = {}, weak cnt = {}", + Rc::strong_count(&b), + Rc::weak_count(&b) + ); + println!("b next item = {:?}", b.tail()); + + if let Some(link) = a.tail() { + *link.borrow_mut() = Rc::downgrade(&b); + } + + println!( + "b rc count after changing a = {}, b weak cnt = {}", + Rc::strong_count(&b), + Rc::weak_count(&b) + ); + println!( + "a rc count after changing a = {}, a weak cnt = {}", + Rc::strong_count(&a), + Rc::weak_count(&a) + ); + + // Uncomment the next line to see that we have a cycle; + // it will overflow the stack + println!("a next item = {:?}", a.tail()); +} +``` +下图为上面代码的内存布局示意图: + +![注释](../../assets/34.png) + +下面再总结一下Weak的特点: + +- 可访问,但没有所有权,不增加引用计数,因此不会影响被引用值的释放回收; +- 可由Rc调用downgrade方法转换成Weak; +- Weak可使用upgrade方法转换成Option>,如果资源已经被释放,则Option的值是None; +- 常用于解决循环引用的问题。