在测试函数上声明生命周期

时间:2016-10-07 01:19:25

标签: rust lifetime

我正在进行一项无法编译的测试:

#[test]
fn node_cost_dequeue() {
    let mut queue: BinaryHeap<&NodeCost> = BinaryHeap::new();
    let cost_1: NodeCost = NodeCost::new(1, 50, 0);
    let cost_2: NodeCost = NodeCost::new(2, 30, 0);
    let cost_3: NodeCost = NodeCost::new(3, 80, 0);
    queue.push(&cost_1);
    queue.push(&cost_2);
    queue.push(&cost_3);
    assert_eq!(2, (*queue.pop().unwrap()).id);
}

error: cost_1 does not live long enough

中的结果

附加信息“借款人之前借入的价值下降”。

所以我尝试添加显式的生命周期注释。

#[test]
fn node_cost_dequeue() {
    let mut queue: BinaryHeap<&'a NodeCost> = BinaryHeap::new();
    let cost_1: NodeCost<'a> = NodeCost::new(1, 50, 0);
    let cost_2: NodeCost<'a> = NodeCost::new(2, 30, 0);
    let cost_3: NodeCost<'a> = NodeCost::new(3, 80, 0);
    queue.push(&cost_1);
    queue.push(&cost_2);
    queue.push(&cost_3);
    assert_eq!(2, (*queue.pop().unwrap()).id);
}

这会产生use of undeclared lifetime name 'a

所以,我试图在函数

上声明它
fn node_cost_dequeue<'a>() -> () {

但这导致error: functions used as tests must have signature fn() -> ()

我是否在正确的轨道上?我该如何宣布这一生?

1 个答案:

答案 0 :(得分:6)

这告诉你的是......

所有内容都以相反的顺序删除。cost_1将在queue之前删除..因为它在queue之后声明。因此queue引用了cost_1,因为现在在方法结束时删除了值queue现在引用了......没有? cost_1已被删除queue仍处于“活着状态” - 即使它即将被删除。

要清楚,事件序列很重要,因为BinaryHeap实例正在存储引用。它没有自己的内容。

事件的顺序是:

  • 声明存储引用的BinaryHeap实例
  • 声明cost_1cost_2cost_3,其引用将插入BinaryHeap
  • 将引用添加到BinaryHeap
  • 执行断言。
  • 删除cost_3
  • 删除cost_2
  • 删除cost_1
  • BinaryHeap引用现在指向什么?这些项目已被删除。
  • 删除BinaryHeap

上面列表中的粗体项是编译器保护您的内容。可能无效的指针。

简单的修复方法是反转声明顺序,以便对cost_1的所有引用都过时queue

let cost_1: NodeCost = NodeCost::new(1, 50, 0);
let cost_2: NodeCost = NodeCost::new(2, 30, 0);
let cost_3: NodeCost = NodeCost::new(3, 80, 0);
let mut queue: BinaryHeap<&NodeCost> = BinaryHeap::new();

这是一个有效的example on the playground

事件的顺序现在是:

  • 声明cost_1cost_2cost_3,其引用将插入BinaryHeap
  • 声明存储引用的BinaryHeap实例
  • 将引用添加到BinaryHeap
  • 执行断言。
  • 删除BinaryHeap引用可能会消失,因为它们引用的项目仍然有效。
  • 删除cost_3
  • 删除cost_2
  • 删除cost_1