rust 生命周期(八)

生命周期定律和原则

1.借用检查器:

Rust 编译器使用借用检查器来验证所有引用在其使用的整个过程中都是有效的。借用检查器通过生命周期来跟踪引用。

2.显式生命周期注解:

当涉及多个引用时,可能需要显式地指定生命周期,以帮助编译器理解引用之间的关系。生命周期注解使用 'a、'b 等来表示。

3.生命周期省略规则(Lifetime Elision Rules):

Rust 编译器在某些情况下能够自动推断生命周期,以下是编译器自动推断生命周期的三条规则:

  • 每个引用参数都有它自己的生命周期参数。例如,&T 被推断为 &'a T。
  • 如果只有一个输入生命周期参数,那么这个生命周期会被赋给所有输出生命周期参数。例如,fn foo(x: &str) -> &str 被推断为 fn foo<'a>(x: &'a str) -> &'a str。
  • 如果有多个输入生命周期参数,其中之一是 &self 或 &mut self,那么 self 的生命周期会被赋给所有输出生命周期参数。这条规则适用于方法。
4.生命周期的命名和使用:

生命周期注解 'a 是一个泛型参数,可以像其他泛型参数一样使用。生命周期注解需要用在函数签名、结构体定义和实现上。

5.结构体中的生命周期:

如果结构体包含引用,则需要在结构体定义中指定生命周期注解,以确保引用的有效性。

6.函数中的生命周期:

在函数中,如果输入参数和返回值之间存在引用关系,则需要显式指定生命周期。

示例和应用
以下是一些具体示例,以帮助理解这些规则和原则:

结构体中的生命周期


struct Borrowed<'a> {
    part: &'a str,
}

impl<'a> Borrowed<'a> {
    fn new(s: &'a str) -> Borrowed<'a> {
        Borrowed { part: s }
    }

    fn part(&self) -> &'a str {
        self.part
    }
}
函数中的生命周期


fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
方法中的生命周期省略


impl<'a> Borrowed<'a> {
    fn new(s: &'a str) -> Borrowed<'a> {
        Borrowed { part: s }
    }

    // 省略后的生命周期注解
    fn part(&self) -> &str {
        self.part
    }
}

经典的错误解析

第一个例子正常:
let string1 = String::from("long string is long");
let result;
{
    let string2 = "xyzssssssssssssssssssssssssss";
    result = longest(string1.as_str(), string2);
    // 这里 result 的生命周期与 string2 相同
    println!("result:{}", result);
}
// string2 超出作用域,result 无法再使用
println!("result_v2:{}", result); // 这行代码会报错

在这个例子中:

string2 是一个字符串字面值(静态切片,&'static str),它的生命周期是 'static,意味着它在整个程序运行期间都是有效的。
longest 函数返回的引用要么指向 string1,要么指向 string2。
因为 string2 是静态的,即使在局部作用域结束后,result 依然有效。

第二个例子报错:
let string1 = String::from("long string is long");
let result;
{
    let string2 = String::from("xyzssssssssssssssssssssssssss");
    result = longest(string1.as_str(), string2.as_str());
    // 这里 result 的生命周期与 string2 相同
    println!("result:{}", result);
}
// string2 超出作用域,result 无法再使用
println!("result_v2:{}", result); // 这行代码会报错

在这个例子中:

string2 是一个 String 对象,它的生命周期仅在内部作用域中有效。
longest 函数返回的引用要么指向 string1,要么指向 string2.as_str()。
当内部作用域结束时,string2 被销毁,导致 string2.as_str() 变得无效。
因此,如果 longest 返回 string2.as_str(),则 result 在内部作用域结束后将变为无效引用,编译器会因此报错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gitxuzan_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值