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

Rust中外层结构体存储内层结构体引用的惯用方式及堆分配咨询

Rust堆分配大结构体相关问题

问题背景

我当前使用的代码如下:

struct Inner {
    value1: i32,
    value2: i32,
}

pub struct Outer<'a> {
    vectors: Vec<&'a Inner>,
}

impl<'a> Outer<'a> {
    pub fn new() -> Self {
        let inner = Inner {
            value1: 0,
            value2: 0,
        };
        let mut vectors = Vec::new();
        vectors.push(&inner);
        Outer { vectors: vectors }
    }
}

运行时出现以下错误:

无法返回引用局部变量inner的值
返回的值引用了当前函数拥有的数据

experiment.rs(17, 22): inner在此处被借用

我需要分配一个非常大的Inner对象(例如数百MB的位图),希望直接在堆上创建它,现咨询以下问题:

  1. 在Rust中实现此需求最惯用的方式是使用Box::new还是Rc<>?
  2. 经搜索得知似乎必须通过这两种方式包装结构体才能实现,此结论是否正确?
  3. Vector显然不需要此类包装,如何让我的结构体更像Vector,无需包装即可存储在堆上?

问题解答

1. 惯用方式选择

如果你的Inner对象不需要被多个所有者共享,优先用Box::new——这是Rust里最基础、最惯用的堆分配方式,没有额外的引用计数开销,语义也最清晰:就是把单个值放到堆上,由Box独占所有权。

如果需要多个地方同时持有这个大对象的所有权(比如多个Outer或者其他结构体都要引用它,且不想手动管理生命周期),再考虑用Rc<>。但如果只是单纯要把大对象放堆上,Box完全足够,没必要上Rc。

2. 是否必须用包装类型?

这个结论不完全正确。

Rust里的普通结构体默认是栈分配,但如果结构体内部包含了堆分配的成员(比如Vec、String、Box),那结构体本身虽然在栈上,但它的核心数据是在堆上的。不过如果你的Inner是纯栈分配类型(比如只包含i32这类基本类型),那要把整个结构体放到堆上,确实需要用Box或者其他智能指针包装——因为Rust没有语法直接把普通结构体标记为堆分配。

但反过来想:如果你的Inner本身就包含大的堆分配数据(比如你的位图可以用Vec<u8>存储),那即使Inner本身在栈上,它的大内存还是在堆上,这时候也可以不用Box包装。不过你要的是“直接在堆上创建整个Inner对象”,那还是得靠Box这类包装。

3. 让结构体像Vec一样无需包装就在堆上?

Vec之所以看起来不用包装就存堆上,是因为它本身就是一个智能指针类型:Vec的栈上部分只是一个包含指针、长度、容量的小结构体,真正的数据在堆上。

如果你想让自己的结构体也做到这点,有两种思路:

  • 把结构体内部的大数据用堆分配类型承载:比如你的位图用Vec<u8>作为Inner的成员,这样Inner的栈部分很小,大内存自动在堆上,不需要额外包装。
  • 自定义类似Vec的智能指针:用unsafe代码实现一个自定义的堆分配结构体,手动管理堆内存(比如模仿Box的实现),但这种方式复杂度高,除非有特殊需求,否则不推荐——直接用Box或者让结构体包含堆分配成员就够了。

另外,你原来代码里的错误本质是生命周期问题:你把栈上的inner的引用放进Vec然后返回,栈上的inner在函数结束后就销毁了,引用自然失效。换成Vec<Box<Inner>>之后,就能直接持有所有权,不会有生命周期问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:53:26