Rust 生命周期

17 Mar 2025 | 5 分钟阅读
  • 生命周期定义了引用的有效范围。
  • 生命周期是隐式的并被推断出来。
  • Rust 使用泛型生命周期参数来确保使用实际有效的引用。

使用生命周期防止悬空引用

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

让我们看一个简单的例子

输出


Rust Lifetime

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

借用检查器

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


Rust Lifetime

在上面的例子中,我们用 'a' 标注了变量 'a' 的生命周期,并用 'b 标注了变量 'b' 的生命周期。在编译时,Rust 将拒绝此程序,因为 'a' 变量的生命周期大于 'b' 变量的生命周期。可以通过修复上面的代码,从而不会出现编译错误。


Rust Lifetime

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

生命周期注解语法

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

生命周期注解语法的步骤

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

下面给出了一些生命周期注解语法的例子

  • &i32                     // 引用
  • & 'a i32              // 具有给定生命周期的引用。
  • & 'a mut i32    // 具有给定生命周期的可变引用。

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

'a 代表引用的生命周期。每个引用都有一个与之相关的生命周期。我们也可以在函数签名中使用生命周期注解。泛型生命周期参数使用在尖括号 <> 之间,并且尖括号放置在函数名称和参数列表之间。我们来看

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

如果一个函数包含一个名为 'y' 的变量。

如果 'y' 是一个不可变引用,则参数列表将是

如果 'y' 是一个可变引用,则参数列表将是

Both & 'a i32 和 & 'a mut i32 类似。唯一的区别是 'a 放在 & 和 mut 之间。

& mut i32 意味着 "对 i32 的可变引用"。

& 'a mut i32 意味着 "对具有生命周期 'a 的 i32 的可变引用"。

结构体中的生命周期注解

我们也可以像在函数中使用的那样,在结构体中使用显式生命周期。

让我们来看看

让我们看一个简单的例子

输出

9

impl 块

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

让我们看一个简单的例子

输出

Value of x is : 90

多个生命周期

我们可以有两种可能性

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

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

在上面的例子中,引用 x 和 y 具有相同的生命周期,即 'a。

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

在上面的例子中,引用 x 和 y 具有不同的生命周期,即 'a 和 'b。

'static

名为 'static 的生命周期是一个特殊的生命周期。它表示某些东西具有 'static 生命周期,将在整个程序中具有生命周期。主要将 'static 生命周期用于字符串。具有 'static 生命周期的引用在整个程序中都有效。

让我们来看看

生命周期省略

生命周期省略是一个推断算法,它使常见的模式更符合人体工程学。生命周期省略使程序省略。

生命周期省略可以在任何地方使用:

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

生命周期省略可以以两种方式出现

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

让我们来看看

生命周期省略的规则

  • 每个通过引用传递的参数都有一个不同的生命周期注解。
fn fun( x : &i32, y : &i32)
	{ 
	} 
fn fun<'a , 'b>( x :& 'a i32, y : & 'b i32)
	{
	}
  • 如果单个参数通过引用传递,则该参数的生命周期将分配给所有省略的输出生命周期。
fn fun(x : i32, y : &i32) -> &i32
	{
	}
fn fun<'a>(x : i32, y : & 'a i32) -> & 'a i3
	{
	}
  • 如果通过引用传递多个参数,并且其中之一是 &self 或 &mut self,则 self 的生命周期将分配给所有省略的输出生命周期。
fn fun(&self, x : &str)
	{
	}
fn fun<'a,'b>(& 'a self, x : & 'b str) -> & 'a str
	{
	}

例如

fn fun( x : &str);                                   // 省略形式。

fn fun<'a>(x : & 'a str) -> & 'a str;    // 展开形式。


下一主题#