[英]Lifetimes for references to values stored in vector
在以下 rust 示例中, Values
结构包含值列表, Refs
结构包含对这些值的一些引用。 此代码产生编译器错误,显示在帖子底部,表明在generate_ref
self.values
中本质上必须具有'a
的生命周期,即使用于生成ref1
的引用在其自己的代码中,也无法生成ref2
堵塞。
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
),但每个频道只存在一个广播器。
虽然可以使用split_at_mut
之类的方法将多个可变引用返回到Vec
中,但它的可扩展性并不高,而且很少值得麻烦。 推荐的解决方案是通过索引而不是通过引用来引用元素,这会从您的代码中删除所有生命周期,并使其更加简单和易于管理:
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
中删除元素,因为这会改变所有的索引,但是这个问题可以通过使用像generational_arena
这样的板条箱来解决,它就像Vec
但它返回的索引是有效的并且即使元素被移除也仍然存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.