【问题标题】:How to appease the borrow checker when returning reference to filtered vector of external references返回对外部引用的过滤向量的引用时如何安抚借用检查器
【发布时间】:2017-03-06 05:52:48
【问题描述】:

我正在尝试实现一个查找函数,该函数将返回一个对包含在self 值中的值的可变引用。通常,由于返回的引用指向 lookup 函数 (self.verts) 之外拥有的数据,借用检查器认为这没有问题。但是,在我的情况下,我在返回引用并将其绑定到新的拥有名称之前过滤 self.verts。当我尝试从该本地拥有的数组中返回一个值时,我得到了编译时错误:

error: `vs` does not live long enough
  --> src/util/graph.rs:18:37
   |
18 |         if vs.len() > 0 { Some(&mut vs[0]) } else { None }
   |                                     ^^ does not live long enough
19 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the body at 16:75...
  --> src/util/graph.rs:16:76
   |
16 |       pub fn lookup_id<'a>(&'a mut self, id: &str) -> Option<&'a mut Vertex> {
   |  ____________________________________________________________________________^ starting here...
17 | |         let vs:Vec<&mut Vertex> = self.verts.iter_mut().filter(|x| x.id == id).collect();
18 | |         if vs.len() > 0 { Some(&mut vs[0]) } else { None }
19 | |     }
   | |_____^ ...ending here

我知道我无法返回对本地拥有的内容的引用,并且我怀疑编译器就是这样解释我的代码的,但这不是我想要做的。想要做的是返回对self.verts 向量中的值的引用,以便返回的引用具有相同的生命周期以及正在执行查找的结构。这是我目前的尝试:

pub fn lookup_id<'a>(&'a mut self, id: &str) -> Option<&'a mut Vertex> {
    let vs:Vec<&'a mut Vertex> = self.verts.iter_mut().filter(|x| x.id == id).collect();
    if vs.len() > 0 { Some(&mut vs[0]) } else { None }
}

此代码无法编译,因为vs does not live long enough。如何告诉编译器想要返回包含在 vs 中的引用而不是对 vs 的引用?

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    您正在返回&amp;mut &amp;mut Vertex

    如果您要丢弃其余元素,则可以进行惰性计算: self.verts.iter_mut().filter(|x| x.id == id).next()

    【讨论】:

      【解决方案2】:

      我怀疑像&amp;mut &amp;mut Vertex 这样的东西。不幸的是,在vs 之前没有&amp;mut,还有其他几个编译器错误。事实证明,Rust 在索引时返回引用,这是我不知道的。我不得不检查std::vec 模块,我发现remove() 直接返回值。此代码有效:

      pub fn lookup_id(&mut self, id: &str) -> Option<&mut Vertex> {
          let mut vs:Vec<&mut Vertex> = self.verts.iter_mut().filter(|x| x.id == id).collect();
          if vs.len() > 0 { Some(vs.remove(0)) } else { None }
      }
      

      然而,这个版本更干净:

      pub fn lookup_id(&self, id: &str) -> Option<&Vertex> {
          self.verts.iter().find(|x| x.id == id)
      }
      

      【讨论】:

        猜你喜欢
        • 2019-12-03
        • 2023-04-11
        • 1970-01-01
        • 1970-01-01
        • 2017-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-04
        相关资源
        最近更新 更多