【RUST】生命周期

在RUST中,每一个引用都存在有一个lifetime,也就是引用有效的范围,平时情况下,我们可以不去显示的去声明它,但是有些特殊的情况需要显示注明。注明生命周期这种事在其他语言并不存在

使用生命周期方式悬空指针

    {
        let r;                // ---------+-- 'a
                              //          |
        {                     //          |
            let x = 5;        // -+-- 'b  |
            r = &x;           //  |       |
        }                     // -+       |
                              //          |
        println!("r: {}", r); //          |
    }                         // ---------+

这段代码编译会报错,是因为r这个引用的对象生命周期已经结束了

generic lifetime parameter

fn main() {
    let string1 = String::from("abcd");
    let string2 = "xyz";

    let result = longest(string1.as_str(), string2);
    println!("The longest string is {}", result);
}

fn longest(x: &str, y: &str) -> &str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这段代码也是报错的,报错信息如下:

$ cargo run
   Compiling chapter10 v0.1.0 (file:///projects/chapter10)
error[E0106]: missing lifetime specifier
 --> src/main.rs:9:33
  |
9 | fn longest(x: &str, y: &str) -> &str {
  |               ----     ----     ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
help: consider introducing a named lifetime parameter
  |
9 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
  |           ++++     ++          ++          ++

For more information about this error, try `rustc --explain E0106`.
error: could not compile `chapter10` due to previous error

主要是代码我们不知道返回的具体是X还是Y,这里我们需要加上生命周期注释

Lifetime Annotation Syntax

首先我们要知道,生命周期注释并不会改变引用的存活时间,它只是描述了不同引用存活时间的关系,注解单个参数并没有任何意义,因为它描述的是一种关系

具体语法是就是’a,'b这种,然后我们看下面的代码

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这个方法声明表示返回值的生命周期等于入参生命周期最小的一个,如果不符合这个标准,就编译报错

代码1:

fn main() {
    let string1 = String::from("long string is long");

    {
        let string2 = String::from("xyz");
        let result = longest(string1.as_str(), string2.as_str());
        println!("The longest string is {}", result);
    }
}

我们可以看到result1和string2的作用域一致,都是比string1小的,所以编译通过

代码2:

fn main() {
    let string1 = String::from("long string is long");
    let result;
    {
        let string2 = String::from("xyz");
        result = longest(string1.as_str(), string2.as_str());
    }
    println!("The longest string is {}", result);
}

这个报错,因为result的作用域超过了string2

Lifetime Annotations in Struct Definitions

struct也可以包含引用,我们也需要加上生命周期的注解

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

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = ImportantExcerpt {
        part: first_sentence,
    };
}

上面代码的意思是ImportantExcerpt的生命周期不能超过part引用的周期

Lifetime Elision

fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

像这段代码,参数和返回值都是引用,但是我们没有使用生命周期注解,这是由于rust在某些场景可以推断,它推断的依据在于:

  • 形参的生命周期
  • 声明返回值的生命周期
  • 实际返回的生命周期

这里具体有某些规则

规则1:
有多少个参数,就有多少生命周期,比如
比如:

fn longest(x: &str, y: &str) -> &str {

编译器会识别为:

fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &str {

但是呢,编译器计算不出返回类型的生命周期,所以编译会报错

规则2:
如果只有一个参数,所有都是它
比如

fn first_word(s: &str) -> &str {

编译器会识别为:

fn first_word<'a>(s: &'a str) -> &'a str {

规则3:
如果方法参数有&self 或者&mut self,那么self的生命周期就会给返回值

The Static Lifetime

'static代表这个引用在整个程序都存在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值