RUST学习-生命周期

RUST的生命周期是指RUST的编译器用来处理悬垂引用的规则

什么是悬垂引用:指生命周期外的变量,引用了本生命周期外的数据,因为这时候被引用的数据在离开被引用的作用域会被回收掉,导致最终引用了一个空值,而RUST的编译器是不允许这种行为产生的

RUST对函数生命周期的检查是通过一个组件引用检查器实现的

几种引用的说明

见下面函数

1
2
3
4
5
6
7
fn largest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
return x;
} else {
return y;
}
}

由于res离开函数largest就被回收掉了所以也无法编译通过会报错:cannot return reference to local variable res

1
2
3
4
fn largest(x: &str) -> &String {
let res=String::from("a");
return &res;
}

largest是无法编译通过的会报错:missing lifetime specifier,因为返回值的生命周期无法判断返回的是a还是b,导致编译错误,解决方案需要手动声明函数引用的生命周期,注意泛型里的’a

1
2
3
4
5
6
7
fn largest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
return x;
} else {
return y;
}
}

函数的泛型+声明周期

生命周期是特殊的泛型需要这么声明

1
2
3
4
5
6
7
8

fn largest<'a, T: PartialOrd>(x: &'a T, y: &'a T) -> &'a T {
if x > y {
return x;
} else {
return y;
}
}

RUST省略生命周期的方案

我们在编写函数一般不会手动指定生命周期那么,RUST是如何来推断出函数的生命周期呢,主要是遵循以下规则:

首先RUST的函数分为输入生命周期(引用参数),和输出生命周期(返回值),如果通过输入生命周期无法推断出输出生命周期就会报错,那么如何推导出输出生命周期呢需要遵循以下三个原则:

  1. 如果没有手动指定生命周期,且有多个引用参数,则每个引用参数有不同的生命周期
  2. 如果只有一个输入生命周期,则可以把当前生命周期赋予输出生命周期
  3. 如果是一个函数即第一个参数是&self或者&mut self,则可以把&self或者&mut self的输入生命周期赋予给输出生命周期