延长'for'变量的生命

时间:2014-08-23 16:44:43

标签: rust

当我在Rust 0.12.0中编译下面的代码时,我收到以下错误:

error: borrowed value does not live long enough
let _ = match re.captures(a_line.unwrap().as_slice()) {

如何延长 a_line 的生命周期,以便 c1 可以推送到 vect1

let vect = process_file(filename_ref);
...
fn process_file(filename: &str) -> Vec<&str> {

    let re = regex!(r"^(\w+)\t(\w+)\t(\w+)\t(\w+)\n$");
    let mut vect1 = Vec::new();

    let filepath = Path::new(filename);
    let _ = match File::open(&filepath) {
        Ok(f) => {
            let mut filebuffer = BufferedReader::new(f);
            for a_line in filebuffer.lines() {
                let _ = match re.captures(a_line.unwrap().as_slice()) {
                    Some(c) =>  {
                        let c1 = c.at(1);
                        vect1.push(c1);
                        ...
                    },
                   ...
               };
           } // end for
       },
       Err(e) => println!("Error: {}", e)
   };

   return vect1;

}

1 个答案:

答案 0 :(得分:3)

简短的回答是,不,你不能只是扩展&#39;像这样的变量的生命周期。

这是一个连接类型的游戏:

  • .lines返回Lines个实例,即Iterator<IoResult<String>>
  • a_lineIoResult <String> = Result<String, IoError>,因此.unwrap会返回String
  • .as_slice提供字符串数据的非拥有视图,该数据通过引用的'a生命周期,静态限制为仅在String时可用存在避免在C ++中悬空引用和使用后免费的问题(更多关于String&str的对比:this answer&amp; the strings guide)。
  • .captures需要&str生命周期('t)并尝试返回持续时间长的Captures。在这种情况下,&str的生命周期是Stringa_line的生命周期,因此cCaptures只存储数据的&str有效期很长。
  • .at返回'tCaptures存储的数据的生命周期为&str,也就是说,返回的&str仅保证最后只要原始captures投放到String(这可能比原始c1存在的时间长,因为它会在内存中管理文本)

因此,String只会持续a_line String的{​​{1}},并且String的范围限定在循环中,也就是说,每次单步执行在循环中,您得到一个新的vect1,它在最后被解除分配。如果编译器通过允许它放在String中让它逃脱,代码将容易使用 - 释放后/悬空参考内存安全错误&str每个&str点在每次迭代结束时释放into(例如,vect1行上的return vect1中的所有&str都指向垃圾。

要解决这个问题,你需要削减内存依赖性:目前String s不能控制自己的内存,因此依赖于&#34; parent&#34; String被正确放置。相反,你可以通过使它们成为完全成熟的vect1.push(c1.to_string())来给矢量内容控制它自己的命运(好吧,记忆)。 vect1。这将使Vec<String>成为a_line,然后这些值与循环内的vect1值之间不再存在连接。然后可以在不影响{{1}}的内容的情况下尽可能多地释放/修改/传播该变量。