繁体   English   中英

对存储在向量中的值的引用的生命周期

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM