-
Weak<T>是一种非拥有性的引用。 -
它不增加强引用计数,只增加一个独立的"弱引用计数"。
-
当所有强引用消失时,数据会被立即释放,无论还有多少个
Weak引用存在。 -
访问
Weak指向的数据时,必须先尝试将其"升级"(upgrade)为Rc或Arc。如果数据已被释放,升级会失败(返回None)。 -
主要方法:
Weak::new():创建一个空的弱引用。Rc::downgrade(&rc):从强引用Rc<T>,创建弱引用Weak<T>。
-
weak.upgrade(): 尝试将Weak<T>升级为Option<Rc<T>>。如果数据已释放,返回None。 -
Rc::weak_count(&rc):获取指向该数据的弱引用数量(主要用于调试)。
5.1 双向链表 / 树结构(父子关系)
在树结构中,父节点持有子节点的强引用(拥有权),而子节点需要知道父节点是谁,但不能拥有父节点(否则形成环)。因此,子节点持有一个指向父节点的 Weak 引用。
rust
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
#[derive(Debug)]
struct Node {
value: i32,
parent: RefCell<Weak<Node>>, // 指向父节点的弱引用
children: RefCell<Vec<Rc<Node>>>, // 指向子节点的强引用
}
fn main() {
// 创建一个父节点
let node1 = Rc::new(Node {
value: 1,
parent: RefCell::new(Weak::new()), // 指向父节点的弱引用,默认初始值为None
children: RefCell::new(Vec::new()), // 指向子节点的强引用,默认初始值为空Vec
});
// 创建一个子节点
let node2 = Rc::new(Node {
value: 2,
parent: RefCell::new(Weak::new()), // 指向父节点的弱引用,默认初始值为None
children: RefCell::new(Vec::new()), // 指向子节点的强引用,默认初始值为空Vec
});
*node2.parent.borrow_mut() = Rc::downgrade(&node1); // 将node2的父节点弱引用指向node1
node1.children.borrow_mut().push(Rc::clone(&node2)); // 将node2的强引用添加到node1的子节点Vec中
println!("{:?}", node1);
println!("{:?}", node2);
println!("{:?}", node2.parent.borrow().upgrade()); // 将node2的父节点弱引用升级为强引用
}
5.2 图结构(无向图/网状结构)
rust
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
#[derive(Debug)]
struct Vertex { // 顶点
value: i32,
neighbors: RefCell<Vec<Weak<Vertex>>>, // 邻居
}
fn main() {
// 创建一个顶点v1,初始邻居为空Vec
let v1 = Rc::new(Vertex {
value: 1,
neighbors: RefCell::new(Vec::new()), // 邻居,默认初始值为空Vec
});
// 创建一个顶点v2,初始邻居为空Vec
let v2 = Rc::new(Vertex {
value: 2,
neighbors: RefCell::new(Vec::new()), // 邻居,默认初始值为空Vec
});
// 创建一个顶点v3,初始邻居为空Vec
let v3 = Rc::new(Vertex {
value: 3,
neighbors: RefCell::new(Vec::new()), // 邻居,默认初始值为空Vec
});
v1.neighbors.borrow_mut().push(Rc::downgrade(&v2)); // 将v2添加到v1的邻居中
v2.neighbors.borrow_mut().push(Rc::downgrade(&v1)); // 将v1添加到v2的邻居中
v1.neighbors.borrow_mut().push(Rc::downgrade(&v3)); // 将v3添加到v1的邻居中
println!("{:?}", v1);
println!("{:?}", v2);
println!(
"{:?}",
v1.neighbors
.borrow() // 获取v1的邻居的读取引用
.iter() // 迭代v1的邻居
.map(|w| w.upgrade()) // 将v1的邻居的弱引用升级为强引用
.collect::<Vec<_>>() // 收集升级后的强引用到Vec中
);
}