生命周期定义了引用有效的范围。
生命周期是隐含的和推断的。
Rust使用通用生命周期参数来确保使用有效的实际引用。
预防与生命周期的悬空引用
当程序试图访问无效引用时称为悬空引用,所指向无效资源的指针称为悬空指针。
看看一个简单的例子:
fn main()
{
let a;
{
let b = 10;
a = &b;
}
println!("a : {}",a);
}
输出结果如下 -
在上面的示例中,外部作用域包含a
变量,并且它不包含任何值。 内部范围包含变量b
,它存储的值为10
。b
变量的引用存储在变量a
中。 当内部范围结束时,尝试访问a
的值。 Rust编译器将抛出一个编译错误,因为a
变量指的是变量的位置超出了范围。 Rust将使用借用检查器确定代码无效。
借用检查器
借用检查器用于解决悬挂引用的问题。 借用检查器用于比较范围以确定它们是否有效。
在上面的例子中,注释了a
变量的生命周期,a
和b
变量的生命周期带有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
代表参考的生命周期。每个参考都有与之相关的生命周期。也可以在函数签名中使用生命周期注释。 通用生命周期参数在角括号<>
之间使用,角括号放在函数名和参数列表之间。
示例 -
fn fun<'a>(...);
在上面的例子中,fun
是具有一个生命周期的函数名,即'a
。 如果函数包含两个具有两个不同生命周期的参考参数,则它可以表示为:
fn fun<'a,'b>(...);
如果'y'
是不可变引用,那么参数列表将是:
fn fun<'a>(y : & 'a i32);
如果'y'
是可变引用,那么参数列表将是:
fn fun<'a>(y : & 'a mut i32);
两个&'a i32
和&'a mut i32
都很相似。 唯一的区别是'a
放在&
和mut
之间。
&mut i32
的意思是“对i32的可变引用”。&'a mut i32
表示“对具有生命周期’的i32
的可变引用”。
结构中的生命周期注释
也可以在结构中使用显式生命周期,就像在函数中使用的一样。
下面来看看一个示例:
struct Example
x : & 'a i32, // x is a variable of type i32 that has the lifetime 'a.
下面来看一个简单的例子:
struct Example<'a> {
x: &'a i32,
}
fn main() {
let y = &9;
let b = Example{ x: y };
println!("{}", b.x);
}
执行上面示例代码,得到以下结果 -
9
impl块
可以实现具有生命周期'a
使用impl
块的结构类型。
下面来看一个简单的例子:
struct Example<'a> {
x: &'a i32,
}
impl<'a> Example<'a>
{
fn display(&self)
{
print!("Value of x is : {}",self.x);
}
}
fn main() {
let y = &90;
let b = Example{ x: y };
b.display();
}
执行上面示例代码,得到以下结果 -
Value of x is : 90
多个生命周期
有两种可能性:
- 多个引用具有相同的生命周期。
- 多个引用具有不同的生命周期。
当引用具有相同的生命周期时。
fn fun <'a>(x: & 'a i32 , y: & 'a i32) -> & 'a i32
//block of code.
在上述情况下,引用x
和y
都具有相同的生命周期,即'a
。
当引用具有不同的生命周期时。如下 -
fn fun<'a , 'b>(x: & 'a i32 , y: & 'b i32)
// block of code.
在上述情况下,参考x
和y
都具有不同的生命周期,即分别为'a
和'b
。
‘static
'static
的生命周期是特殊的生命周期。它表示某些东西具有生命周期'static
将在整个程序中具有生命周期。 主要是'static
生命周期与字符串一起使用。 具有“静态生命周期”的引用对整个程序有效。
示例 :
let s : & 'static str = "Yiibai tutorial" ;
生命周期椭圆
生命周期椭圆是一种推理算法,它使常见的模式更符合人体工程学。生命周期椭圆使一个程序被淘汰。
生命周期椭圆可以在任何地方使用:
& 'a T
& 'a mut T
T<'a>
生命周期椭圆可以以两种方式出现:
- 输入生命周期:输入生命周期是与函数参数关联的生命周期。
- 输出生存期:输出生存期是与函数返回类型关联的生命周期。
示例 -
fn fun<'a>( x : & 'a i32); // input lifetime
fn fun<'a>() -> & 'a i32; // output lifetime
fn fun<'a>(x : & 'a i32)-> & 'a i32; // Both input and output lifetime.