我知道
Arc
中的数据存储在堆中,当两个对象有 Arc
相互引用时,它们不会被编译器自动删除。以下代码显示了这种情况。
use std::{cell::RefCell, sync::Arc};
impl Drop for Data {
fn drop(&mut self) {
println!("data {} drops here", self.x);
}
}
pub struct Data {
pub x: usize,
pub next: Option<Arc<RefCell<Data>>>,
}
fn main() {
let data1 = RefCell::new(Data { x: 42, next: None });
let data2 = RefCell::new(Data { x: 53, next: None });
let ptr1 = Arc::new(data1);
let ptr2 = Arc::new(data2);
ptr1.borrow_mut().next = Some(ptr2.clone());
ptr2.borrow_mut().next = Some(ptr1.clone());
println!("Hello, world!");
}
输出只是一行
Hello, world!
,这里没有掉落
那是因为即使指针
ptr1
和ptr2
在main
函数的末尾被删除,data1
和data2
的引用计数器仍然是1
,没有减少到0
。
这好像是Rust Programming Language中提到的cycle Arc,它建议我们使用
Weak
来解决问题。
但是,当我想删除它时,我可以将
Data.Some(Arc<RefCell<Data>>)
替换为 None
,这样会删除数据。
use std::{cell::RefCell, sync::Arc};
impl Drop for Data {
fn drop(&mut self) {
println!("data {} drops here", self.x);
}
}
pub struct Data {
pub x: usize,
pub next: Option<Arc<RefCell<Data>>>,
}
fn main() {
let data1 = RefCell::new(Data { x: 42, next: None });
let data2 = RefCell::new(Data { x: 53, next: None });
let ptr1 = Arc::new(data1);
let ptr2 = Arc::new(data2);
ptr1.borrow_mut().next = Some(ptr2.clone());
ptr2.borrow_mut().next = Some(ptr1.clone());
// =========================================
ptr1.borrow_mut().next = None;
// =========================================
println!("Hello, world!");
}
输出是:
Hello, world!
data 53 drops here
data 42 drops here
所以,在某种程度上,我能否在没有
Arc
的情况下避免Weak
中的所有循环引用并构建一些数据结构,就像维护一个包含其父节点和子节点的三节点一样?