You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中实现结构体的循环依赖?

Rust中实现互相依赖结构体的正确方式

你遇到的错误核心原因是:创建Rc::new(b)时,b的所有权被完全转移到了Rc内部,后续再尝试访问原变量b就会触发所有权错误。要在Rust中实现这种双向依赖的结构体,需要结合**引用计数(Rc/Arc)和内部可变性(RefCell/Mutex)**来解决,以下是具体方案:

基础解决方案:Rc + RefCell(单线程场景)

首先需要调整结构体定义,用Rc<RefCell<B>>替代直接的Rc<B>,因为Rc本身是不可变的,要修改结构体内部的字段需要借助RefCell提供的内部可变性。

use std::rc::{Rc, RefCell};

struct A {
    b: Rc<RefCell<B>>
}

struct B {
    a: Option<Rc<A>>
}

fn main() {
    // 先将B包装为Rc<RefCell>,保留共享引用
    let b = Rc::new(RefCell::new(B { a: None }));
    // 创建A时,clone b的引用(不转移所有权)
    let a = Rc::new(A { b: Rc::clone(&b) });
    // 通过RefCell的borrow_mut()获取可变引用,修改B内部的a字段
    b.borrow_mut().a = Some(a);
}

关键要点:

  • Rc:提供共享所有权,通过Rc::clone()复制引用,所有clone出的Rc实例共享同一个底层数据,引用计数会自动增减。
  • RefCell:允许在持有不可变外部引用的情况下,修改内部数据(借用规则在运行时检查,而非编译时),通过borrow_mut()获取可变引用,borrow()获取不可变引用。

避免内存泄漏:使用Weak弱引用

上面的基础方案存在循环引用问题:A持有B的强引用,B持有A的强引用,导致两者的引用计数永远无法降到0,最终引发内存泄漏。解决这个问题的办法是把其中一方的强引用改为Weak弱引用:

use std::rc::{Rc, RefCell, Weak};

struct A {
    b: Rc<RefCell<B>>
}

struct B {
    a: Option<Weak<A>>
}

fn main() {
    let b = Rc::new(RefCell::new(B { a: None }));
    let a = Rc::new(A { b: Rc::clone(&b) });
    // 将Rc<A>降级为Weak<A>,不增加引用计数
    b.borrow_mut().a = Some(Rc::downgrade(&a));
    
    // 使用Weak引用时,需要通过upgrade()尝试转为强引用(返回Option<Rc<A>>)
    if let Some(a_rc) = b.borrow().a.as_ref().and_then(|weak_a| weak_a.upgrade()) {
        // 成功获取到A的强引用,可以正常使用
        println!("成功访问到A的引用");
    }
}

Weak的作用:

  • Weak是不增加引用计数的弱引用,当所有强引用(Rc实例)都被销毁后,底层对象会被自动回收,此时Weak引用的upgrade()会返回None。
  • 弱引用适合这种不需要保持对象存活的双向关联场景,从根本上避免循环引用导致的内存泄漏。

多线程场景的替代方案

如果你的代码需要在多线程环境下运行,把Rc换成Arc(原子引用计数,线程安全),把RefCell换成Mutex或RwLock(线程安全的内部可变性容器)即可:

use std::sync::{Arc, Mutex};

struct A {
    b: Arc<Mutex<B>>
}

struct B {
    a: Option<Arc<A>>
}

fn main() {
    let b = Arc::new(Mutex::new(B { a: None }));
    let a = Arc::new(A { b: Arc::clone(&b) });
    // 多线程下需要lock()获取Mutex的可变引用,注意处理可能的PoisonError
    if let Ok(mut b_mut) = b.lock() {
        b_mut.a = Some(a);
    }
}

内容的提问来源于stack exchange,提问作者Rocky Pulley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:11:30