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

如何将内部对象的方法实现到外部结构体?(Rust示例)

实现方法暴露的方案

要让Outer能直接调用Inner的方法,核心是实现Rust的Deref和DerefMut trait——这也是Box能直接调用内部对象方法的底层逻辑。同时需要修正原代码中的内存安全问题,避免出现悬垂指针。

步骤1:修复Outer的所有权模型

原代码中Outer::new接收&mut T,但这样Outer持有的指针指向的对象可能在外部被释放,导致悬垂指针。我们需要让Outer拥有内部对象的所有权,像Box一样在堆上分配内存:

use std::ops::{Deref, DerefMut};

struct Outer<T>(*mut T);

impl<T> Outer<T> {
    // 接收T的所有权,在堆上分配内存并存储指针
    pub fn new(value: T) -> Outer<T> {
        // 将值包装进Box后转成裸指针,让Outer持有所有权
        let ptr = Box::into_raw(Box::new(value));
        Outer(ptr)
    }
}

步骤2:实现Deref和DerefMut trait

通过实现这两个trait,Outer会被自动解引用为内部的T,从而可以直接调用T的方法:

impl<T> Deref for Outer<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        // 裸指针转不可变引用,因Outer拥有所有权,指针始终有效
        unsafe { &*self.0 }
    }
}

impl<T> DerefMut for Outer<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        // 裸指针转可变引用
        unsafe { &mut *self.0 }
    }
}

步骤3:实现Drop trait避免内存泄漏

因为使用了裸指针,Rust不会自动回收堆上的内存,所以需要实现Drop trait来手动释放内存:

impl<T> Drop for Outer<T> {
    fn drop(&mut self) {
        // 将裸指针转回Box,借助Box的自动析构释放内存
        unsafe {
            Box::from_raw(self.0);
        }
    }
}

完整可运行代码

use std::ops::{Deref, DerefMut};

struct Outer<T>(*mut T);

impl<T> Outer<T> {
    pub fn new(value: T) -> Outer<T> {
        let ptr = Box::into_raw(Box::new(value));
        Outer(ptr)
    }
}

impl<T> Deref for Outer<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { &*self.0 }
    }
}

impl<T> DerefMut for Outer<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *self.0 }
    }
}

impl<T> Drop for Outer<T> {
    fn drop(&mut self) {
        unsafe {
            Box::from_raw(self.0);
        }
    }
}

struct Inner(pub i32);
impl Inner {
    pub fn do_thing(&self) {
        println!("did the thing {}", self.0);
    }

    pub fn modify(&mut self, val: i32) {
        self.0 = val;
    }
}

fn main() {
    let mut outer = Outer::new(Inner(2));
    outer.do_thing(); // 直接调用Inner的方法
    outer.modify(5);
    outer.do_thing(); // 输出"did the thing 5"
}

关键说明

  • Deref和DerefMut实现了自动解引用逻辑,让Outer<T>的引用可以无缝转换为T的引用。
  • 必须实现Drop trait,否则堆上的内存无法被自动回收,会造成内存泄漏。
  • unsafe块的使用是因为裸指针操作无法被Rust编译器自动验证安全性,这里因Outer完全持有内部对象的所有权,所以操作是安全的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:15:44