HashMap的键没有足够长的生命周期

5

我正在尝试使用HashMap<String, &Trait>,但是我收到了一个我不理解的错误信息。以下是代码(playground):

use std::collections::HashMap;

trait Trait {}

struct Struct;

impl Trait for Struct {}

fn main() {
    let mut map: HashMap<String, &Trait> = HashMap::new();
    let s = Struct;
    map.insert("key".to_string(), &s);
}

这是我收到的错误信息:

error[E0597]: `s` does not live long enough
  --> src/main.rs:12:36
   |
12 |     map.insert("key".to_string(), &s);
   |                                    ^ borrowed value does not live long enough
13 | }
   | - `s` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

这里发生了什么?有没有解决方法?
1个回答

9
这个问题已经通过 非词法生命周期 得到解决,从 Rust 2018 开始不再是一个问题。下面的答案适用于使用旧版 Rust 的人。

maps的寿命长,因此在map的生命周期中的某个时刻(就在销毁之前),s将会变成无效。通过改变它们的构造顺序,以及销毁顺序,可以解决这个问题:

let s = Struct;
let mut map: HashMap<String, &Trait> = HashMap::new();
map.insert("key".to_string(), &s);

如果您希望 HashMap 拥有这些引用,可以使用拥有所有权的指针:
let mut map: HashMap<String, Box<Trait>> = HashMap::new();
let s = Struct;
map.insert("key".to_string(), Box::new(s));

谢谢,这个可以用。但是你能解释一下为什么 maps 存活更久吗?我以为变量在作用域结束时被销毁,所以有特定的销毁顺序吗? - franza
4
有的,破坏的顺序与建造的顺序相反,因为如果你有 let x = 1; let y = T(&x);y 的解构器可能需要访问 x - Veedrac
噢,我明白了。我认为这是因为那些变量被分配在堆栈中。 - franza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接