我相信这个函数声明告诉Rust函数输出的生命周期与它的s个参数的生命周期相同:

fn substr<'a>(s: &'a str, until: u32) -> &'a str;
         ^^^^

在我看来,编译器只需要知道(1):

fn substr(s: &'a str, until: u32) -> &'a str;

函数名后面的注释<'a>是什么意思?为什么编译器需要它,它用它做什么?


(1) 当前位置我知道它需要知道的更少,因为一生都在逃避.但这个问题是关于明确指定生命周期 的.

推荐答案

让我进一步阐述前面的答案…

What does the annotation <'a> after the function name mean?

我不会用"注释"这个词.就像<T>引入通用type参数一样,<'a>引入通用lifetime参数.如果不先介绍泛型参数,就不能使用任何泛型参数.对于泛型函数,这种介绍就发生在它们的名称之后.你可以把泛型函数看作是一系列函数.所以,本质上,每一个泛型参数的组合都有一个函数.substr::<'x>将在一生中成为该功能家族的特定成员'x.

如果你不清楚什么时候以及为什么我们必须明确地描述生命,请继续阅读…

生存期参数始终与所有引用类型关联.当你写作的时候

fn main() {
    let x = 28374;
    let r = &x;
}

编译器知道x位于主函数的作用域中,并用大括号括起来.在内部,它用一些生存期参数标识这个范围.对我们来说,它还没有命名.当你取地址x时,你会得到一个特定引用类型的值.引用类型是二维引用类型族的一种成员.一个轴是参考点的类型,另一个轴是用于两个约束的生命周期:

  1. 引用类型的lifetime参数表示可以保留该引用多长时间的上限
  2. 引用类型的lifetime参数表示可以使引用指向的对象的生命周期的下限.

总之,这些限制在Rust的记忆安全故事中起着至关重要的作用.这里的目标是避免悬而未决的引用.我们想排除指向某个我们不再被允许使用的内存区域的引用,因为它用来指向的东西已经不存在了.

造成混淆的一个潜在原因可能是,生命周期 参数在大多数情况下是不可见的.但这并不意味着他们不在那里.引用always的类型中有一个生存期参数.但是这样一个生命周期参数不一定要有名字,而且大多数时候我们也不需要提及它,因为编译器可以自动为生命周期参数指定名字.这被称为"终身省略".例如,在以下情况下,您不需要提及任何生命周期 参数:

fn substr(s: &str, until: u32) -> &str {…}

但这样写也没关系.这实际上是一种更明确的语法

fn substr<'a>(s: &'a str, until: u32) -> &'a str {…}

在这里,编译器会自动为"输入生存期"和"输出生存期"指定相同的名称,因为这是一种非常常见的模式,很可能正是您想要的.因为这种模式非常常见,编译器让我们不用说任何关于生命周期的事情就可以逃脱.根据两条"终身省略"规则(至少有here条记录),这种更明确的形式就是我们的意思

在某些情况下,explicit个生命周期 参数是not个可选参数.例如,如果你写

fn min<T: Ord>(x: &T, y: &T) -> &T {
    if x <= y {
        x
    } else {
        y
    }
}

编译器会抱怨,因为它会将上述声明解释为

fn min<'a, 'b, 'c, T: Ord>(x: &'a T, y: &'b T) -> &'c T { … }

因此,对于每个参考,都会引入一个单独的生命周期 参数.但是,在这个签名中没有关于生命周期参数如何相互关联的信息.这个通用函数的用户可以使用any个生命周期.这是它体内的一个问题.我们想退回xy.但x型是&'a T型.这与返回类型&'c T不兼容.y也是如此.由于编译器不知道这些生命周期如何相互关联,因此将这些引用作为&'c T类型的引用返回是不安全的.

&'a T型值到&'c T型值安全吗?对如果'a的生命周期 等于or greater,那么'c的生命周期 是安全的.或者换句话说'a: 'c.所以,我们写这个

fn min<'a, 'b, 'c, T: Ord>(x: &'a T, y: &'b T) -> &'c T
      where 'a: 'c, 'b: 'c
{ … }

而且不用让编译器抱怨函数的主体就可以顺利完成.但它实际上是unnecessarily复杂.我们也可以简单地写

fn min<'a, T: Ord>(x: &'a T, y: &'a T) -> &'a T { … }

并对所有内容使用一个生命周期参数.编译器能够推断'a是调用站点参数引用的最短生存期,因为我们对两个参数使用了相同的生存期名称.这个生命周期正是我们需要的返回类型.

我希望这能回答你的问题.:)

Rust相关问答推荐

如何在Rust中在屏幕中间打印内容?

给定使用newype习语定义的类型上的铁 rust Vec,有没有方法获得底层原始类型的一部分?

有没有更好的方法从HashMap的条目初始化 struct ?

关于如何初始化弱 struct 字段的语法问题

如何在 struct 的自定义序列化程序中使用serde序列化_WITH

为什么铁 rust S似乎有内在的易变性?

我应该将哪些文件放入我的GitHub存储库

如何使用Actix Web for Rust高效地为大文件服务

如果变量本身不是None,如何返回;如果没有,则返回None&Quot;?

如何将实现多个特征的 struct 传递给接受这些特征为&;mut?

Rust从关联函数启动线程

为什么BufReader实际上没有缓冲短寻道?

如何获取模块树?

trait 对象指针的生命周期

为什么Rust编译器会忽略模板参数应具有静态生命周期?

实现泛型的 Trait 方法中的文字

在线程中运行时,TCPListener(服务器)在 ip 列表中的服务器实例之前没有从客户端接受所有客户端的请求

如何在 Rust 中将 bson::Bson 转换为 Vec

Rust 中的let是做什么的?

Rust 为什么 (u32, u32) 的枚举变体的大小小于 (u64)?