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

如何存储Rust回调返回的可变引用数据?解决生命周期报错

Rust新手问题:如何长期存储回调返回的可变引用?

我是Rust新手,不确定“callback”是否为正确术语。以下是基于某个crate编写的简化代码:

struct Thing {}

trait CrateSuppliedTrait {
    fn start_handling() {
        // 假设这部分由crate实现,会启动一个长期运行的进程...
    }
    fn handle(
        &mut self,
        thing: &mut Thing
    );
}

struct MyHandler<'a> {
    things: Vec<&'a mut Thing>,
}

impl<'a> CrateSuppliedTrait for MyHandler<'a> {
    // 每次有需要处理的内容时调用
    fn handle(
        &mut self,
        thing: &mut Thing // crate实现的代码会调用这个handle方法并传入该引用
    ) {
        // 如何正确存储这份数据?
        // 编译报错:"lifetime may not live long enough"
        self.things.push(thing);
    }
}

fn main() {
    MyHandler::start_handling();
}

我希望将返回的Thing可变引用长期存储在内存中,请问最佳实现方式是什么?

编译时出现如下错误:

Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
  --> src/main.rs:23:9
   |
15 | impl<'a> CrateSuppliedTrait for MyHandler<'a> {
   |      -- lifetime `'a` defined here
...
19 |         thing: &mut Thing // Crate implements code that calls this handle method and returns this
   |                - let's call the lifetime of this reference `'1`
...
23 |         self.things.push(thing);
   |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`

error: could not compile `playground` (bin "playground") due to 1 previous error

问题分析

报错的本质是:你试图把一个临时生命周期的引用(thing的'1)存入要求生命周期'a的向量中,Rust编译器无法保证thing的生命周期能覆盖'a,因此拒绝编译,避免出现悬垂引用。

解决方案

根据你的实际使用场景,选择以下方案:

  • 方案1:获取Thing的所有权(优先推荐)
    如果crate允许返回Thing的所有权,直接修改MyHandler存储所有权而非引用:

    struct MyHandler {
        things: Vec<Thing>,
    }
    
    impl CrateSuppliedTrait for MyHandler {
        fn handle(&mut self, thing: Thing) { // 假设crate可以返回所有权
            self.things.push(thing);
        }
    }
    

    如果crate只能返回引用,可检查Thing是否实现了Clone,通过thing.clone()复制后存储;若无法克隆,需确认是否能从crate处获取所有权。

  • 方案2:用智能指针实现共享可变访问
    若必须保留对Thing的访问且无法获取所有权,使用Arc<Mutex<Thing>>(或Arc<RwLock<Thing>>)来管理共享生命周期:

    use std::sync::{Arc, Mutex};
    
    struct Thing {}
    
    trait CrateSuppliedTrait {
        fn start_handling();
        fn handle(&mut self, thing: Arc<Mutex<Thing>>);
    }
    
    struct MyHandler {
        things: Vec<Arc<Mutex<Thing>>>,
    }
    
    impl CrateSuppliedTrait for MyHandler {
        fn start_handling() {
            // crate实现逻辑
        }
        fn handle(&mut self, thing: Arc<Mutex<Thing>>) {
            self.things.push(thing);
        }
    }
    
    fn main() {
        MyHandler::start_handling();
    }
    

    Arc会维护引用计数,确保Thing在所有持有者都不再使用时才被释放,Mutex保证可变访问的线程安全。

  • 方案3:复制Thing中的数据而非存储引用
    如果Thing的生命周期确实很短,无法长期持有引用,可提取其中需要的数据进行存储:

    struct Thing {
        data: i32, // 假设该字段可复制/克隆
    }
    
    struct MyHandler {
        thing_data: Vec<i32>,
    }
    
    impl CrateSuppliedTrait for MyHandler {
        fn handle(&mut self, thing: &mut Thing) {
            self.thing_data.push(thing.data); // 复制数据而非存储引用
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 09:34:51