rust - 对存储在向量中的值的引用的生命周期
问题描述
在下面的 rust 示例中,一个Values
结构包含一个值列表,一个Refs
结构包含对这些值的一些引用。此代码产生编译器错误,显示在帖子底部,表明 ingenerate_ref
self.values
本质上必须具有 生命周期,即使用于生成的引用位于其自己的代码块中'a
,也无法生成。ref2
ref1
pub struct Values {
values: Vec<i32>,
}
impl<'a> Values {
pub fn new() -> Values {
Values { values: vec![] }
}
pub fn generate_ref(&mut self) -> &'a mut i32 {
self.values.push(1);
self.values.last_mut().unwrap()
}
}
pub struct Refs<'a> {
ref1: &'a mut i32,
ref2: &'a mut i32,
}
impl<'a> Refs<'a> {
pub fn new(values: &'a mut Values) -> Refs {
let ref1 = { values.generate_ref() };
let ref2 = { values.generate_ref() };
Refs { ref1, ref2 }
}
}
fn main() {
let mut values = Values::new();
let refs = Refs::new(&mut values);
let ref3 = { values.generate_ref() };
}
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src\main.rs:12:9
|
12 | self.values.last_mut().unwrap()
| ^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 10:5...
--> src\main.rs:10:5
|
10 | / pub fn generate_ref(&mut self) -> &'a mut i32 {
11 | | self.values.push(1);
12 | | self.values.last_mut().unwrap()
13 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:12:9
|
12 | self.values.last_mut().unwrap()
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
--> src\main.rs:5:6
|
5 | impl<'a> Values {
| ^^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:12:9
|
12 | self.values.last_mut().unwrap()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我真正需要的是确保从返回的引用generate_ref
与存储在Values
. 我怎样才能做到这一点?如果这是不可能的,是否有另一种方法来构建在 Rust 中有效的代码?
编辑
有关更多上下文,这是一个简化的示例。在实际实现中,Values
保持一个bus::Bus
向接收者广播数据。接收器由Bus
. 各种其他结构包含接收器 ( bus::BusReader
) 和对广播器 () 的引用&mut bus::Bus
,但每个频道仅存在一个广播器。
解决方案
虽然可以将多个可变引用返回到Vec
using 方法中,split_at_mut
但它的可扩展性不是很好,而且很少值得麻烦。推荐的解决方案是通过索引而不是通过引用来引用元素,这会从您的代码中删除所有生命周期,并使其更加简单和易于管理:
pub struct Values {
values: Vec<i32>,
}
impl Values {
pub fn new() -> Values {
Values { values: vec![] }
}
pub fn generate_index(&mut self) -> usize {
self.values.push(1);
self.values.len() - 1
}
}
pub struct Indices {
idx1: usize,
idx2: usize,
}
impl Indices {
pub fn new(values: &mut Values) -> Self {
Indices {
idx1: values.generate_index(),
idx2: values.generate_index(),
}
}
}
fn main() {
let mut values = Values::new();
let indicies = Indices::new(&mut values);
let idx3 = values.generate_index();
}
上述方法的一个缺点是您永远无法从其中删除元素,Vec
因为这会改变所有索引,但是可以通过使用类似于 a 的板条箱来解决该问题,generational_arena
但Vec
它返回的索引是有效的并且即使当元素被移除时。
推荐阅读
- javascript - 如何避免在指令中调用 `$parent` 范围
- c - 在 C 中的 GTK+ TreeView 中使用 Pango 标记
- matlab - 求解方程 {exponential *prod Exponential(ln)}
- android - Android 使用蓝牙检测智能手机
- javascript - Squish - 录制时不进行验证
- jquery - 动态输入文件类型字段
- python - 如何为函数内的变量分配新值?
- c# - System.Data.SqlClient.SqlException:'关键字'between'附近的语法不正确。'
- r - 在函数中将变量分配给全局环境不起作用 R
- ruby-on-rails - Rails:如何获取具有相同关联数组的实例