这是我的代码:
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(),
}
}
}
我在引用&Query<T>
的地方继续“缺少生命周期说明符”。如何解决此错误?
答案 0 :(得分:8)
首先,请注意&T
/ &mut T
和*const T
/ *mut T
是Rust中不同类型的指针。前者被称为&#34;参考&#34;并且它们以各种方式进行静态检查(包括借用分析),并且它们不能为空或指向某些无效对象。后者被称为&#34;原始指针&#34;并且主要用于抽象实现和FFI。
因此,写作
Query {
data: name,
prev: ptr::null(),
next: ptr::null(),
}
当prev
和next
类型&Whatever
不正确时,ptr::null()
会返回类型*const Whatever
的值,这些值与{{不兼容(安全) 1}}。
Rust中的引用总是有一些与之关联的生命周期 - 编译器使用它来检查引用始终指向有效的数据片段。此生命周期在引用类型中指定:&Whatever
。在大多数情况下,编译器可以自动推断出正确的生命周期,因此您很少需要在局部变量类型中甚至在函数声明中编写它们:
&'a T
但是,当您想要对结构进行引用时,编译器无法推断结构声明中的生命周期(因为它可以是任意的并且取决于结构值的方式 使用),因此您需要明确指定生命周期参数:
let x: &str = "hello";
fn print_str(s: &str) { println!("{}", s); }
在这种特殊情况下,似乎你想要实现某种双重链接结构。不幸的是,Rust引用不能用于此。终身要求禁止通过引用创建循环 - 如果struct Query<'a, T> {
data: T,
prev: &'a Query<'a, T>,
next: &'a Query<'a, T>,
}
在其中x
引用y
,则只能在x
中存储y
的引用。构建这种结构的唯一方法是通过变异:
let mut x = SomeStructure(None);
let y = SomeStructure(Some(&x));
x.0 = Some(&y);
但你不能改变一个指向它的引用的对象,也就是说,上面的代码是无效的。
您尝试实现的目标通常称为intrusive data structures,目前它们在Rust中得不到很好的支持。有一个RFC issue,我们可能会在将来看到它们取得一些进展。
你可以在这里做几件事,最简单的一件事就是以你不需要使用双重链接结构的方式重构你的代码。几乎总是可以将数据放在像Vec
这样的连续数组中,并使用索引来访问它,并且很可能由于缓存局部性,即使对于简单的遍历也会更有效。
另一个选择是使用非侵入式链表,例如可用的链表in the standard library。
当然,你总是可以使用原始指针。在需要它们时使用它们没有任何问题,并且大多数标准库抽象(如上面的链表)在内部以某种方式使用它们。然而,在你的情况下,它们应该是最后的手段 - 很可能有办法在没有它们的情况下做你想做的事。