避免在没有 Weak in Rust 的情况下循环 Arc 引用

问题描述 投票:0回答:0

我知道

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
中的所有循环引用并构建一些数据结构,就像维护一个包含其父节点和子节点的三节点一样?

rust automatic-ref-counting
© www.soinside.com 2019 - 2024. All rights reserved.