获取'Missing Lifetime specifier'错误

use*_*563 2 compiler-errors lifetime rust

这是我的代码:

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(),
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我一直在引用'缺少生命周期说明符' &Query<T>.我该如何解决这个错误?

Vla*_*eev 8

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

因此,写作

Query {
    data: name,
    prev: ptr::null(),
    next: ptr::null(),
}
Run Code Online (Sandbox Code Playgroud)

何时prevnext类型&Whatever不正确 - ptr::null()返回*const Whatever与(安全)不兼容的类型的值&Whatever.

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

let x: &str = "hello";

fn print_str(s: &str) { println!("{}", s); }
Run Code Online (Sandbox Code Playgroud)

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

struct Query<'a, T> {
    data: T,
    prev: &'a Query<'a, T>,
    next: &'a Query<'a, T>,
}
Run Code Online (Sandbox Code Playgroud)

但是,在这种特殊情况下,您似乎希望实现某种双重链接结构.不幸的是,Rust引用不能用于此.生命周期要求禁止通过引用创建循环 - 如果在其中有引用,则无法存储对xin 的引用.构建这种结构的唯一方法是通过变异:yxy

let mut x = SomeStructure(None);
let y = SomeStructure(Some(&x));
x.0 = Some(&y);
Run Code Online (Sandbox Code Playgroud)

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

你想要实现的东西通常被称为侵入式数据结构,现在它们在Rust中得不到很好的支持.有一个RFC问题,我们可能会在将来看到它们取得一些进展.

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

另一种选择是使用非侵入式链表,如标准库中可用的链表.

当然,你总是可以使用原始指针.在需要它们时使用它们没有任何问题,并且大多数标准库抽象(如上面的链表)在内部以某种方式使用它们.然而,在你的情况下,它们应该是最后的手段 - 最有可能的方法是在没有它们的情况下做你想做的事情.