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

Rust中循环引用的构建优化方案咨询

Rust 不可变父子循环引用的轻量实现

问题场景

在C++中,我通过以下代码实现了不可变的父子循环引用:

#include <memory>
#include <iostream>

struct Parent;
struct Child;

struct Parent {
  std::shared_ptr<const Child> child;
};

struct Child {
  std::weak_ptr<const Parent> parent;
};


auto makeStructs() -> std::shared_ptr<const Parent>
{
  auto parent = std::make_shared<Parent>();
  parent->child = std::make_shared<const Child>(parent);
  return parent;
}

初始化完成后,parent和child始终保持不可变,其他组件可通过共享指针安全引用它们。

但在Rust中,我当前的实现不得不引入RefCell和Option——这两者在初始化完成后就不再需要,却带来了不必要的运行时开销和代码复杂度:

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

pub struct Parent {
    child : Option<Rc<Child>>
}

pub struct Child {
    parent: Weak<RefCell<Parent>>
}

pub fn make_structs() -> Rc<RefCell<Parent>>
{
    let parent = Rc::new(RefCell::new(Parent{child: None}));
    parent.borrow_mut().child = Some(Rc::new(Child {parent : Rc::downgrade(&parent)}));
    
    return parent;
}

我希望实现更轻量化的版本,不需要RefCell和Option,结构如下:

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

pub struct Parent {
    child : Rc<Child>
}

struct Child {
    parent: Weak<Parent>
}

pub fn make_structs() -> Rc<Parent>
{
   // 需要实现的逻辑
}

优化实现

可以借助Rc::get_mut方法(仅当Rc的引用计数为1时允许获取可变引用),结合临时占位的方式完成初始化,完全避免RefCell和Option的使用:

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

pub struct Parent {
    child: Rc<Child>,
}

pub struct Child {
    parent: Weak<Parent>,
}

pub fn make_structs() -> Rc<Parent> {
    // 创建临时Parent实例,用空Weak的Child占位(后续会替换)
    let mut parent = Rc::new(Parent {
        child: unsafe { Rc::new_unchecked(Child { parent: Weak::new() }) },
    });

    // 创建持有正确Parent Weak引用的Child
    let child = Rc::new(Child {
        parent: Rc::downgrade(&parent),
    });

    // 此时parent引用计数为1,安全获取可变引用替换child字段
    if let Some(parent_mut) = Rc::get_mut(&mut parent) {
        parent_mut.child = child;
    }

    parent
}

关键说明

  • 安全性:Rc::get_mut的使用是安全的——初始化阶段parent仅被当前作用域持有,引用计数为1,没有其他共享持有者,因此可以安全修改其内部字段。
  • 无额外开销:初始化完成后,Parent和Child都是完全不可变的结构,没有RefCell的运行时借用检查,也没有Option的分支判断开销。
  • 临时不安全操作:Rc::new_unchecked只是临时占位用,后续立刻被正确的Child实例替换,不会产生任何安全风险。

如果不想使用unsafe代码,也可以引入once_cell库的Lazy类型来延迟初始化,但上述原生实现是最轻量化的方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 20:39:52