这个章节主要是为了引出弱引用这个奇怪的概念。
说实在,这个没有什么太好写的,因为内容比较晦涩难懂!
在其它语言中,也常常存在所谓循环引用问题,和大部分问题一样,在其它语言中这些基本上都不是问题。但是在rust中,这是一个致命的问题。
例如有a,b两个点,a指向b,b指向a。
如果根据截止当前的知识(所有权、一个数据也可以有多个所有者),那么rust可能无法释放a所实际指向的数据,或者是因为循环递归导致堆栈溢出。
或者其实我们也没有必要知道为什么,只要知道结论即可,毕竟如果我们不看编译器是怎么写的。所以,有的时候就是看到了概念,看到了例子也是难以理解。
这些都需要借助于一些概念和例子来理解。
堆栈溢出示例(来自原书):
use crate::List::{Cons, Nil}; use std::cell::RefCell; use std::rc::Rc; #[derive(Debug)] enum List { Cons(i32, RefCell<Rc<List>>), Nil, } impl List { fn tail(&self) -> Option<&RefCell<Rc<List>>> { match self { Cons(_, item) => Some(item), Nil => None, } } } fn main() { let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil)))); println!("a initial rc count = {}", Rc::strong_count(&a)); println!("a next item = {:?}", a.tail()); let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a)))); println!("a rc count after b creation = {}", Rc::strong_count(&a)); println!("b initial rc count = {}", Rc::strong_count(&b)); println!("b next item = {:?}", b.tail()); if let Some(link) = a.tail() { *link.borrow_mut() = Rc::clone(&b); } println!("b rc count after changing a = {}", Rc::strong_count(&b)); println!("a rc count after changing a = {}", Rc::strong_count(&a)); // Uncomment the next line to see that we have a cycle; // it will overflow the stack // println!("a next item = {:?}", a.tail()); }
rust在做匹配的时候,会不断找尾巴,结果循着尾巴一直找.....
rust推出一个新的概念:弱引用(weak reference)
所谓弱引用,即指向某个数据,但是这种引用不会产生所有权方面的问题,就如同大部分其它语言那样的美好。
一、重要概念
Rc::downgrade Rc::downgrade 会将 weak_count 加 1,同时返回Weak<T>指针 这个函数用于构建弱引用 Weak::upgrade() Weak<T> 实例的 upgrade 方法,这会返回 Option<Rc<T>>二、例子
书上例子很完善,稍微修改了下:
use std::cell::RefCell; use std::rc::{ Rc, Weak }; #[derive(Debug)] struct Node { value: i32, parent: RefCell<Weak<Node>>, children: RefCell<Vec<Rc<Node>>>, } fn main() { look_weak_ref(); } fn look_weak_ref() { let leaf = Rc::new(Node { value: 3, parent: RefCell::new(Weak::new()), children: RefCell::new(vec![]), }); println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf)); { println!("------------------------------------------------------------------------------"); let branch = Rc::new(Node { value: 5, parent: RefCell::new(Weak::new()), children: RefCell::new(vec![Rc::clone(&leaf)]), }); *leaf.parent.borrow_mut() = Rc::downgrade(&branch); println!("branch strong = {}, weak = {}",Rc::strong_count(&branch),Rc::weak_count(&branch)); println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf)); println!("------------------------------------------------------------------------------"); } println!("leaf parent = {:?}", leaf.parent.borrow().upgrade()); println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf)); }
三、小结
如果我们成心构建导致堆栈溢出的死循环,还是可以的,书上也有这个例子。
但rust提供了可以避免这个的方法,毕竟这种需求还是不鲜见的!
标签:count,leaf,内存,Rc,println,new,strong,泄露,rust From: https://www.cnblogs.com/lzfhope/p/18655762