首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自缓冲读取器的行的生命周期不足,导致无法拆分行

来自缓冲读取器的行的生命周期不足,导致无法拆分行
EN

Stack Overflow用户
提问于 2018-03-22 04:39:41
回答 1查看 138关注 0票数 0

我正在绞尽脑汁想弄清楚Rust的借入/生命周期/所有权属性。也就是说,当使用缓冲的读取器并试图拆分一行时。代码

代码语言:javascript
复制
use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {
    let f = File::open("foo.txt").expect("file not found");
    let f = BufReader::new(f);

    for line in f.lines() {
        let split: Vec<&str> = {
            let ln: String = line.unwrap();
            ln.split(' ').collect()
        };
    }
}

或者任何变体(有或没有指定变量类型,徒劳地试图使其成为可变的,等等)都会导致:

代码语言:javascript
复制
'ln' does not live long enough; borrowed value must only be valid for the static lifetime...

然而,试图伪造一个延长的生命周期,并通过切片从生产线上获取一些数据

代码语言:javascript
复制
let nm = line;
name = &line[..];

或者,即使只是尝试对未经修改的split()变量进行操作,结果也会是:

代码语言:javascript
复制
cannot index into a value of type 'std::result::Result<std::string::String, std::io::Error>'

"borrowed value does not live long enough" seems to blame the wrong thing建议生命周期足够长,可以将每个单词放入它自己的字符串中,但是修改我在the Playground上的原始代码以包括嵌套的for循环仍然会导致

代码语言:javascript
复制
error[E0597]: borrowed value does not live long enough
  --> src/main.rs:11:18
   |
11 |         for w in line.unwrap().split_whitespace() {
   |                  ^^^^^^^^^^^^^ temporary value does not live long enough
...
14 |         }
   |         - temporary value dropped here while still borrowed
15 |     }
   |     - temporary value needs to live until here
   |
   = note: consider using a `let` binding to increase its lifetime

在引用line.unwrap()

最后,我在这里对Rust的生命周期或借用属性有什么误解?

EN

回答 1

Stack Overflow用户

发布于 2018-03-22 11:31:10

你的原始代码在编译时给出的错误是:

代码语言:javascript
复制
error[E0597]: `ln` does not live long enough
  --> src/main.rs:11:13
   |
11 |             ln.split(' ').collect()
   |             ^^ borrowed value does not live long enough
12 |         };
   |         - `ln` dropped here while still borrowed
13 |     }
   |     - borrowed value needs to live until here

error: aborting due to previous error

根据@shepmaster的评论,在发布问题时提供完整的错误信息是一个好主意。

无论如何,它突出了问题:

代码语言:javascript
复制
let split: Vec<&str> = {
    let ln: String = line.unwrap();
    ln.split(' ').collect()
};

您正在创建一个包含对str切片的引用的Vec;切片并不拥有它们被切片的数据,它们实际上是指向必须由另一个变量拥有的数据的指针。因此,对它们进行切片的变量必须比切片存在的时间更长。

在用于初始化Vec的表达式中,创建一个包含正在处理的文本行的String。此字符串的作用域是变量ln是初始化表达式-一旦您离开该作用域,它就会被删除。

然后对字符串执行split操作,这将为字符串片段返回一个迭代器,每个子字符串一个迭代器。不过请记住,迭代器返回的是切片,切片是指向String ln中的子字符串的指针。这些分片的寿命不允许超过ln本身。

希望你现在能看到问题所在。一旦退出初始化表达式,ln就会被删除,但Vec仍将包含str分片。他们指的是什么?

修复方法非常简单。为什么要在这个块中声明ln呢?事实上,为什么在那里有一个块呢?这是可行的:

代码语言:javascript
复制
for line in f.lines() {
    let ln: String = line.unwrap();
    let split: Vec<&str> = ln.split(' ').collect();
    // Now do something with split
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49416082

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档