获取“缺少生命周期说明符"错误 [英] Getting 'Missing Lifetime specifier' error

查看:39
本文介绍了获取“缺少生命周期说明符"错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码:

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 的地方不断收到缺少生命周期说明符".如何修复此错误?

I keep getting 'missing lifetime specifier' where I am referencing &Query<T>. How do I fix this error?

推荐答案

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

First, note that &T/&mut T and *const T/*mut T are different types of pointers in Rust. The former are called "references" and they are statically checked in various ways (including borrowing analysis) and they can't be null or point to some invalid object. The latter are called "raw pointers" and are used primarily in abstractions implementations and for FFI.

因此,写作

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

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

when prev and next are of type &Whatever is incorrect - ptr::null() returns values of type *const Whatever which is not compatible (safely) with &Whatever.

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

References in Rust always have some lifetime associated with them - it is used by the compiler to check that references always point to valid pieces of data. This lifetime is specified in reference type: &'a T. In most cases the compiler can infer correct lifetimes automatically, so you seldom need to write them in types of local variables or even in function declarations:

let x: &str = "hello";

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

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

However, when you want to put references to a structure, there is just no way the compiler can infer the lifetime in the structure declaration (because it can be arbitrary and depends on the way the structure values are used), and so you need to specify lifetime parameters explicitly:

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

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

In this particular case, though, it seems that you want to implement some kind of doubly linked structure. Unfortunately, Rust references can't be used for this. Lifetime requirements prohibit creation of loops via references - you just can't store a reference to x in y if x has a reference to y inside it. The only way such structure can be constructed is through mutation:

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

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

But you can't mutate an object which has a reference pointing to it, that is, the above code is invalid.

您想要实现的目标通常称为 侵入式数据结构,目前它们在 Rust 中并没有得到很好的支持.有一个 RFC 问题,我们可能会看到一些进展未来.

The thing you're trying to achieve is usually called intrusive data structures, and for now they are not well supported in Rust. There is an RFC issue on that, and we may probably see some progress on them in future.

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

There are several things you can do here, the most easiest one probably would be to refactor your code in such a way that you won't need to use a doubly-linked structure. Almost always you can put your data in a contiguous array like Vec and use indices to access it, and most likely it would be more efficient even for simple traversal because of cache locality.

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

Another option would be to use a non-intrusive linked list, like the one which is available in the standard library.

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

And, of course, you can always drop to using raw pointers. There is nothing wrong in using them when they are required, and most of the standard library abstractions (like the linked list above) are using them in some way internally. In your case, however, they should be the last resort - most likely there are ways to do what you want without them.

这篇关于获取“缺少生命周期说明符"错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆