问题描述
我有以下代码,您也可以在 playground 中看到:
struct Node<'a> {
parent: Option<&'a Node<'a>>,name: &'a str,}
fn looper(nodes: &mut Vec<Node>) {
for i in 0..nodes.len() {
let n = &nodes[i];
let next_node = Node {
parent: Some(n),name: "please compile",};
nodes.push(next_node);
}
}
它应该采用 Vec
的 Node
并将 Node
附加到它,以引用 Node
中已有的 Vec
。不幸的是,我收到此错误:
error[E0623]: lifetime mismatch
--> src/main.rs:13:20
|
6 | fn looper(nodes: &mut Vec<Node>) {
| -------------- these two types are declared with different lifetimes...
...
13 | nodes.push(next_node);
| ^^^^^^^^^ ...but data from `nodes` flows into `nodes` here
我该如何编译?在这种情况下如何考虑生命周期的解释将是有用的。我知道这可能是由于 variance 而造成的问题,但我不确定如何重新表述我的问题以提供我想要的功能。
解决方法
一般规则:当某个值的类型或它实现的特征具有生命周期参数时,该生命周期总是长比值本身的生命周期——该值保证引用它包含在被删除之前不会失效。
事实上,在你的例子中我们可以看到,如果不是这种情况,生命周期检查将是不健全的;您正在向 nodes
中添加值,但没有什么可以阻止 looper
从 nodes
中删除 值,这将导致无效引用这些值的任何 parent
引用。
构建一棵树或引用链表的唯一实用方法(没有特殊目的的不安全代码,有一个特定的计划来保持良好的状态)是编写一个递归函数;每个函数调用帧都可以引用由其调用者(及其调用者的调用者等)构造的节点。这被借用检查器接受,因为每个帧都有自己的新的、更短的引用生命周期(一个引用总是可以被视为比它开始时的生命周期更短)。