关于rust:延长字符串切片的借入寿命

Extending borrowed lifetime for String slice

我有一个读取文件的函数,并且针对每一行将其添加到类型为&strHashSet中,但是我不知道如何告诉借阅检查器延长生存期。 >

到目前为止,这是我的职能:

1
2
3
4
5
6
7
8
9
10
11
12
fn build_collection_set(reader: &mut BufReader<File>) -> HashSet<&str> {
    let mut collection_set: HashSet<&str> = HashSet::new();

    for line in reader.lines() {
        let line = line.unwrap();
        if line.len() > 0 {
            collection_set.insert(&*line);
        }
    }

    return collection_set;
}

如何让Rust知道我希望将其保留更长的时间?


but I can't work out how to tell the borrow checker to increase the lifetime.

不可能。

以C,C或Rust表示的值的生存期定义为:

  • 根据其词法范围(如果它绑定到自动变量)
  • 根据其动态范围(如果已在堆上分配)

您可以创建引用此值的变量,如果引用的寿命比该值长,则您有一个悬空的引用:

  • 在C和C中,最好不要使用它
  • 在Rust中,编译器将拒绝编译您的代码

为了验证您的程序,Rust编译器将要求您注释引用的生命周期;您将使用诸如&'a T中的'a之类的生命周期批注,这些注释可以命名生命周期,以便记录多个值的生命周期之间的关系。

此处的执行词是文档:生存期是无形的并且不能受到影响,生存期注释'a只是允许引用它的名称。

那么?

每当您发现想要延长引用的生存期时,您应该查看的是延长引用的生存期...或者根本不使用引用而是使用值。

在这种情况下,一个简单的解决方案是返回String而不是&str

1
2
3
4
5
6
7
8
9
10
11
12
fn build_collection_set(reader: &mut BufReader<File>) -> HashSet<String> {
    let mut collection_set = HashSet::new();

    for line in reader.lines() {
        let line = line.unwrap();
        if line.len() > 0 {
            collection_set.insert(line);
        }
    }

    collection_set
}


reader.lines()返回在拥有的String上进行迭代的迭代器。但是,然后在for循环中,将其强制转换为借用的对&str的引用。因此,当迭代器超出范围时,所有借用的引用都将变为无效。考虑使用HashSet<String>代替,这也是零成本,因为字符串被移到HashSet中,因此不会被复制。

工作实例

1
2
3
4
5
6
7
8
9
10
11
fn build_collection_set(reader: &mut BufReader<File>) -> HashSet<String> {
    let mut collection_set: HashSet<String> = HashSet::new();

    for line in reader.lines() {
        let line = line.unwrap();
        if line.len() > 0 {
            collection_set.insert(line);
        }
    }
    collection_set
}