Rust实现简单自定义集合时所有权与生命周期报错的解决方法
问题原因
- 你在调用
self.list.push(user)时,user的所有权已经转移到list中,后续再访问user的字段必然触发use of moved value报错 - 你的
UsersIndex属于自引用结构:试图在同一个结构体的index字段中存储同结构体list元素的引用。Rust借用规则不允许这种设计,一方面list扩容时元素内存地址会变动导致引用悬垂,另一方面生命周期约束也无法满足这种自引用场景,才会触发生命周期相关报错。
实现方案(推荐用下标代替引用)
这个方案无额外性能开销,也不需要引入复杂的智能指针,是这类索引场景最常用的实现:
use std::collections::HashMap; pub struct User { pub id: u32, pub name: String, } pub struct UsersIndex { list: Vec<User>, // 存储id对应在list中的下标,替代引用 index: HashMap<u32, usize>, } impl UsersIndex { pub fn new() -> Self { UsersIndex { list: Vec::new(), index: HashMap::new(), } } pub fn add(&mut self, user: User) { let user_id = user.id; self.list.push(user); // 刚插入的元素下标为list长度-1 let index = self.list.len() - 1; self.index.insert(user_id, index); } pub fn get(&self, id: u32) -> Option<&User> { self.index.get(&id).map(|&idx| &self.list[idx]) } }
如果你的场景需要支持删除操作,可以把Vec<User>替换为Vec<Option<User>>,删除时把对应位置设为None即可,避免移动元素导致已存储的下标全部失效。如果需要多场景共享User所有权,可以用Rc<User>(多线程场景用Arc<User>),list和index都存储Rc<User>的拷贝,通过引用计数共享所有权即可。
内容的提问来源于stack exchange,提问作者broadsw0rd
相关产品推荐
相关产品推荐

