- 此问题在此处已有答案**:
Why can't I store a value and a reference to that value in the same struct?(4个答案)
5天前关闭。
为什么这个代码:
#[derive(Eq, PartialEq, Ord, PartialOrd)]
enum List<'a> {
Cons(isize, &'a List<'a>),
Nil,
}
fn main() {
use List::*;
use pinus::{prelude::*, sync::PineMap};
let table = PineMap::new();
table.insert(Nil, Nil);
let nil = table.get(&Nil).unwrap();
table.insert(Cons(1, nil), Cons(1, nil));
}
导致此错误:
error[E0597]: `table` does not live long enough
--> src/main.rs:12:15
|
12 | let nil = table.get(&Nil).unwrap();
| ^^^^^^^^^^^^^^^ borrowed value does not live long enough
13 | table.insert(Cons(1, nil), Cons(1, nil));
14 | }
| -
| |
| `table` dropped here while still borrowed
| borrow might be used here, when `table` is dropped and runs the `Drop` code for type `PineMap`
我使用一个pinus::sync::PineMap
来确保所有对List
等价示例的引用实际上是对内存中同一对象的引用,我认为一种方法是使用一个表将List
键Map到一个表拥有的List
示例,我正在为它试用PineMap
,因为它的insert
不会移动内存中的项(它的insert借用了&self
,而不是&mut self
),所以对它的List
值的引用将保持有效,并且我可以构建自引用项。
为什么在我的代码中,table
在其作用域的末尾仍然被认为是被借用的?
1条答案
按热度按时间bvjveswy1#
当你把
nil
从表中取出,然后用Cons(1, nil)
把它放回表中时,nil
的类型是一个与table
的生存期绑定的引用,因此你存储的List
的生存期'a
与存储它们的table
绑定。这里的核心问题是,这创建了一个自引用结构体,它引入了无数的问题,你也不能调用任何可变的方法,因为
table
永久地借用了自己。编译器所抱怨的具体问题是,由于元素持有对表的引用,当它被删除时,删除逻辑可能会试图访问正在被销毁的数据,这是不合理的。
我鼓励你阅读Rustonomicon中关于Drop Check的更多信息,这里有一个指导原则:
对于一个泛型类型来说,要正确地实现drop,它的泛型参数必须严格地比它的寿命长。
我没有任何变通办法或解决方案,你除了你不能这样做。