如何存储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
相关产品推荐
相关产品推荐

