橘子味的心
标题:Rust生命周期

生命周期定义了引用有效的范围。
生命周期是隐含的和推断的。
Rust使用通用生命周期参数来确保使用有效的实际引用。

预防与生命周期的悬空引用

当程序试图访问无效引用时称为悬空引用,所指向无效资源的指针称为悬空指针。

看看一个简单的例子:

  1. fn main()
  2. {
  3. let a;
  4. {
  5. let b = 10;
  6. a = &b;
  7. }
  8. println!("a : {}",a);
  9. }
  10. Rust

输出结果如下 -

在上面的示例中,外部作用域包含a变量,并且它不包含任何值。 内部范围包含变量b,它存储的值为10b变量的引用存储在变量a中。 当内部范围结束时,尝试访问a的值。 Rust编译器将抛出一个编译错误,因为a变量指的是变量的位置超出了范围。 Rust将使用借用检查器确定代码无效。

借用检查器

借用检查器用于解决悬挂引用的问题。 借用检查器用于比较范围以确定它们是否有效。

在上面的例子中,注释了a变量的生命周期,ab变量的生命周期带有b变量。 在编译时,Rust将拒绝该程序,因为a变量的生命周期大于b变量的生命周期。 可以修复上面的代码,以便不会发生编译器错误。

在上面的例子中,a变量的生命周期短于b变量的生命周期。 因此,上面的代码运行时没有任何编译错误。

生命周期注释语法

  • 生命周期注释不会改变任何引用的生存时间。
  • 函数还可以使用泛型生存期参数接受任何生命周期的引用。
  • 生命周期注释描述了多个参数的生命周期之间的关系。

生命周期注释语法应遵循的步骤:

  • 生命周期参数的名称应以(')撇号开头。
  • 它们主要是小写和简写。 例如:'a
  • 生命周期参数注释放在引用的&之后,然后是空格以将注释与引用类型分开。

生命周期注释语法的一些示例:

  • &i32 // reference
  • & 'a i32 // reference with a given lifetime.
  • & 'a mut i32 // mutable reference with a given lifetime.

函数签名中的生命周期注释

'a代表参考的生命周期。每个参考都有与之相关的生命周期。也可以在函数签名中使用生命周期注释。 通用生命周期参数在角括号<>之间使用,角括号放在函数名和参数列表之间。

示例 -

  1. fn fun<'a>(...);
  2. Rust

在上面的例子中,fun是具有一个生命周期的函数名,即'a。 如果函数包含两个具有两个不同生命周期的参考参数,则它可以表示为:

  1. fn fun<'a,'b>(...);
  2. Rust

如果'y'是不可变引用,那么参数列表将是:

  1. fn fun<'a>(y : & 'a i32);
  2. Rust

如果'y'是可变引用,那么参数列表将是:

  1. fn fun<'a>(y : & 'a mut i32);
  2. Rust

两个&'a i32&'a mut i32都很相似。 唯一的区别是'a放在&mut之间。

&mut i32的意思是“对i32的可变引用”。
&'a mut i32表示“对具有生命周期’的i32的可变引用”。

结构中的生命周期注释

也可以在结构中使用显式生命周期,就像在函数中使用的一样。

下面来看看一个示例:

  1. struct Example
  2. x : & 'a i32, // x is a variable of type i32 that has the lifetime 'a.
  3. Rust

下面来看一个简单的例子:

  1. struct Example<'a> {
  2. x: &'a i32,
  3. }
  4. fn main() {
  5. let y = &9;
  6. let b = Example{ x: y };
  7. println!("{}", b.x);
  8. }
  9. Rust

执行上面示例代码,得到以下结果 -

impl块

可以实现具有生命周期'a使用impl块的结构类型。

下面来看一个简单的例子:

  1. struct Example<'a> {
  2. x: &'a i32,
  3. }
  4. impl<'a> Example<'a>
  5. {
  6. fn display(&self)
  7. {
  8. print!("Value of x is : {}",self.x);
  9. }
  10. }
  11. fn main() {
  12. let y = &90;
  13. let b = Example{ x: y };
  14. b.display();
  15. }
  16. Rust

执行上面示例代码,得到以下结果 -

  1. Value of x is : 90
  2. Shell

多个生命周期

有两种可能性:

  • 多个引用具有相同的生命周期。
  • 多个引用具有不同的生命周期。

当引用具有相同的生命周期时。

  1. fn fun <'a>(x: & 'a i32 , y: & 'a i32) -> & 'a i32
  2.  
  3. //block of code.
  4. Rust

在上述情况下,引用xy都具有相同的生命周期,即'a

当引用具有不同的生命周期时。如下 -

  1. fn fun<'a , 'b>(x: & 'a i32 , y: & 'b i32)
  2.  
  3. // block of code.
  4. Rust

在上述情况下,参考xy都具有不同的生命周期,即分别为'a'b

‘static

'static的生命周期是特殊的生命周期。它表示某些东西具有生命周期'static将在整个程序中具有生命周期。 主要是'static生命周期与字符串一起使用。 具有“静态生命周期”的引用对整个程序有效。

示例 :

  1. let s : & 'static str = "Yiibai tutorial" ;
  2. Rust

生命周期椭圆

生命周期椭圆是一种推理算法,它使常见的模式更符合人体工程学。生命周期椭圆使一个程序被淘汰。

生命周期椭圆可以在任何地方使用:

  • & 'a T
  • & 'a mut T
  • T<'a>

生命周期椭圆可以以两种方式出现:

  • 输入生命周期:输入生命周期是与函数参数关联的生命周期。
  • 输出生存期:输出生存期是与函数返回类型关联的生命周期。

示例 -

  1. fn fun<'a>( x : & 'a i32); // input lifetime
  2. fn fun<'a>() -> & 'a i32; // output lifetime
  3. fn fun<'a>(x : & 'a i32)-> & 'a i32; // Both input and output lifetime.
  4. Rust