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

Rust结构体成员引用其他成员的实现问题咨询

解决方案:Rust中Owner与Borrower的共享引用问题

问题根源

你最初的代码存在悬垂引用问题:new函数里的局部变量val生命周期仅局限于函数内部,Borrower持有它的引用,但Owner的value是val的拷贝。当new函数返回时,局部变量val被销毁,Borrower的引用指向已释放的内存,这违反了Rust的内存安全规则,因此编译器报错。

基于Rc的正确实现

使用Rc(引用计数智能指针)实现共享所有权是正确的方向,只需通过Deref操作获取内部值的引用,即可适配外部库的需求:

use std::rc::Rc;

struct Owner {
    value: Rc<f32>,
    other: Borrower,
}

impl Owner {
    fn new() -> Self {
        let val = Rc::new(0.0);

        Self {
            value: val.clone(),
            other: Borrower::new(val),
        }
    }
}

struct Borrower {
    value: Rc<f32>,
}

impl Borrower {
    fn new(value: Rc<f32>) -> Self {
        // 通过&*value获取内部f32的不可变引用,满足外部库需求
        external_library_needs_ref(&*value);
        Self { value }
    }
}

// 模拟外部库函数
fn external_library_needs_ref(_: &f32) {}

关键说明

  • Rc<f32>实现了Deref<Target=f32>,因此&*value会自动解引用为&f32,直接传递给需要该类型参数的外部库函数即可。
  • Rc::clone仅增加引用计数,不会拷贝底层的f32值,性能开销极小。

若需可变引用的场景

如果外部库需要可变引用,需结合RefCell实现内部可变性(Rc本身仅支持共享不可变访问):

use std::rc::Rc;
use std::cell::RefCell;

struct Owner {
    value: Rc<RefCell<f32>>,
    other: Borrower,
}

impl Owner {
    fn new() -> Self {
        let val = Rc::new(RefCell::new(0.0));

        Self {
            value: val.clone(),
            other: Borrower::new(val),
        }
    }
}

struct Borrower {
    value: Rc<RefCell<f32>>,
}

impl Borrower {
    fn new(value: Rc<RefCell<f32>>) -> Self {
        // 通过borrow_mut()获取可变引用,注意运行时会检查借用规则
        let mut val_ref = value.borrow_mut();
        external_library_needs_mut_ref(&mut *val_ref);
        Self { value }
    }
}

// 模拟需要可变引用的外部库函数
fn external_library_needs_mut_ref(_: &mut f32) {}

为什么不推荐外部存储值

将值放在结构体外部虽然能暂时解决问题,但会破坏代码的封装性,让所有权关系变得模糊,增加维护成本。使用Rc+Deref(或RefCell)的方案既能保证内存安全,又能维持结构体的封装性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:42:43