引用计数循环列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#[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,
}
}
}
use std::rc::Rc;
use std::cell::RefCell;
use crate::List::{Cons,Nil};

fn main() {
let a = Rc::new(Cons(5,RefCell::new(Rc::new(Nil))));
println!("1 a rc count = {}",Rc::strong_count(&a));//1
println!("1 a tail = {:?}",a.tail()); //1

let b = Rc::new(Cons(10,RefCell::new(Rc::clone(&a))));
println!("2 a rc count = {}",Rc::strong_count(&a));//2
println!("2 b rc count = {}",Rc::strong_count(&b));//1
println!("2,b tail = {:?}",b.tail());

if let Some(link) = a.tail() {
*link.borrow_mut() = Rc::clone(&b);
}

println!("3 a rc count = {}",Rc::strong_count(&a));//2
println!("3 b rc count = {}",Rc::strong_count(&b));//2
//这段打印会溢出,因为构成了循环
//
//println!("2,b tail = {:?}",b.tail());
}


//如果在下面的代码中释放b,会造成a持有b的引用计数,b的引用计数为1
//也就是造成内存泄露

//fn main() {
// let a = Rc::new(Cons(5,RefCell::new(Rc::new(Nil))));
// println!("1 a rc count = {}",Rc::strong_count(&a));//1
// println!("1 a tail = {:?}",a.tail()); //1
// {
// let b = Rc::new(Cons(10,RefCell::new(Rc::clone(&a))));
// println!("2 a rc count = {}",Rc::strong_count(&a));//2
// println!("2 b rc count = {}",Rc::strong_count(&b));//1
// println!("2,b tail = {:?}",b.tail());
//
// if let Some(link) = a.tail() {
// *link.borrow_mut() = Rc::clone(&b);
// }
//
// println!("3 a rc count = {}",Rc::strong_count(&a));//2
// println!("3 b rc count = {}",Rc::strong_count(&b));//2
// //这段打印会溢出,因为构成了循环
// //
// //println!("2,b tail = {:?}",b.tail());
// }
// a持有b,b的内存计数为一,这个内存地址没有被丢弃
// b的引用存在,内存泄露发生
// ....
//}

循环列表完成图