选择 Box<T>、RC<T>、RefCell<T>的依据:
|----------|-----------------|--------------|-----------------|
| | box | Rc | RefCell |
| 统一数据的所有者 | 一个 | 多个 | 一个 |
| 可变性、借用检查 | 可变、不可变借用(编译时检查) | 不可变借用(编译时检查) | 可变、不可变借用(运行时检查) |
| 是否会开辟堆空间 | 是 | 是 | 否 |
案例一、Box实现链表,链表循环
rust
#[derive(Debug)]
pub enum Node {
Value(i32, Box<Node>),
Nil,
}
pub fn test1() {
let list = Box::new(Node::Value(
1,
Box::new(Node::Value(
2,
Box::new(Node::Value(3, Box::new(Node::Nil))),
)),
));
// 循环列表方法一
// let mut current = list;
// while let Node::Value(val, next) = *current {
// println!("Value: {}", val);
// current = next;
// }
// 循环列表方法二
let mut current = list;
loop {
match *current {
Node::Value(val, next) => {
println!("Value: {}", val);
current = next;
}
Node::Nil => break,
}
}
// 定义了一个长度10,全是0的数组
let a = Box::new([0; 10]);
let b = &a;
let c = &a;
let d = &a;
println!("{:?},{:?},{:?},{:?}", a, b, c, d);
}
案例二、分别使用Rc、Box实现链表
rust
use std::rc::Rc;
// Rc
#[derive(Debug)]
enum Node {
Cons(i32, Rc<Node>),
Nil,
}
pub fn test2() {
let list = Rc::new(Node::Cons(
1,
Rc::new(Node::Cons(2, Rc::new(Node::Cons(3, Rc::new(Node::Nil))))),
));
let list2 = Rc::new(Node::Cons(0, Rc::new(Node::Cons(1, Rc::clone(&list)))));
let list3 = Rc::new(Node::Cons(4, Rc::new(Node::Nil)));
println!("{:#?}, {:#?}, {:#?}", list, list2, list3);
}
// Box
#[derive(Debug)]
enum Node2<'a> {
Cons(i32, &'a Box<Node2<'a>>),
Nil,
}
pub fn test22() {
let null = Box::new(Node2::Nil);
let n5 = Box::new(Node2::Cons(1, &null));
let n4 = Box::new(Node2::Cons(1, &n5));
let n3 = Box::new(Node2::Cons(1, &n4));
let n2 = Box::new(Node2::Cons(1, &n3));
let n1 = Box::new(Node2::Cons(1, &n2));
let list = Box::new(Node2::Cons(4, &n1));
println!("{:#?}", list);
}
案例三、使用Box,Rc,RefCell实现链表循环添加,遍历
rust
// 二级指针的链表,一级就够了,box可以删掉,存储过多的变量地址,会降低运行效率。
use std::{cell::RefCell, rc::Rc};
#[derive(Debug)]
enum Node {
Value(i32, Rc<RefCell<Box<Node>>>),
Nil,
}
pub fn test3() {
let list = Rc::new(RefCell::new(Box::new(Node::Nil)));
let mut tmp = Rc::clone(&list);
for i in 1..=10 {
let newNode = Rc::new(RefCell::new(Box::new(Node::Nil)));
*tmp.borrow_mut() = Box::new(Node::Value(i, Rc::clone(&newNode)));
tmp = newNode;
}
let mut tmp = Rc::clone(&list);
while let Node::Value(num, next) = &**(tmp.clone().borrow()) {
println!("{:?}", num);
tmp = Rc::clone(&next);
}
}