收到 'Missing Lifetime specifier' 错误

Getting 'Missing Lifetime specifier' error

这是我的代码:

use std::ptr;

struct Query<T>{
  data: T,
  prev: & Query<T>,
  next: & Query<T>,
}
impl<T> Query<T>{
  fn new(name: T) -> Query<T>{
    Query{
      data: name,
      prev: ptr::null(),
      next: ptr::null(),
    }
  }
}

我一直在 'missing lifetime specifier' 引用 &Query<T>。我该如何解决这个错误?

首先,请注意 &T/&mut T*const T/*mut T 是 Rust 中不同类型的指针。前者称为 "references" 并以各种方式对其进行静态检查(包括借用分析),并且它们不能为 null 或指向某个无效对象。后者称为 "raw pointers",主要用于抽象实现和 FFI。

因此,写作

Query {
    data: name,
    prev: ptr::null(),
    next: ptr::null(),
}

prevnext 属于 &Whatever 类型时不正确 - ptr::null() returns 类型 *const Whatever 的值不兼容(安全地)使用 &Whatever.

Rust 中的引用总是有一些与之关联的生命周期 - 编译器使用它来检查引用是否始终指向有效的数据片段。此生命周期在引用类型中指定:&'a T。在大多数情况下,编译器可以自动推断出正确的生命周期,因此您很少需要将它们写在局部变量类型甚至函数声明中:

let x: &str = "hello";

fn print_str(s: &str) { println!("{}", s); }

但是,当您想要引用结构时,编译器无法在结构声明中推断生命周期(因为它可以是任意的并且取决于结构值的方式 被使用),因此您需要明确指定生命周期参数:

struct Query<'a, T> {
    data: T,
    prev: &'a Query<'a, T>,
    next: &'a Query<'a, T>,
}

不过,在这种特殊情况下,您似乎想要实现某种双向链接结构。不幸的是,Rust 引用不能用于此。生命周期要求禁止通过引用创建循环——如果 x 中有对 y 的引用,你就不能在 y 中存储对 x 的引用。构建这种结构的唯一方法是通过突变:

let mut x = SomeStructure(None);
let y = SomeStructure(Some(&x));
x.0 = Some(&y);

但是你不能改变一个有引用指向它的对象,也就是说,上面的代码是无效的。

您要实现的目标通常被称为 intrusive data structures, and for now they are not well supported in Rust. There is an RFC issue,我们可能会在未来看到一些进展。

您可以在这里做几件事,最简单的可能是以不需要使用双向链接结构的方式重构您的代码。几乎总是可以将数据放在像 Vec 这样的连续数组中,并使用索引来访问它,而且由于缓存的局部性,即使对于简单的遍历,它也很可能会更有效率。

另一种选择是使用非侵入式链表,例如可用的链表 in the standard library

而且,当然,您始终可以放弃使用原始指针。在需要时使用它们并没有错,大多数标准库抽象(如上面的链表)都在内部以某种方式使用它们。但是,在您的情况下,它们应该是最后的手段 - 很可能没有它们也有办法做您想做的事。