生命周期

2021-08-29  本文已影响0人  简书网abc

a、Rust中每一个引用都有其生命周期,也就是引用保持有效的作用域。

大部分时候生命周期是隐含并可以推断的,正如大部分时候类型可以推断一样

b、生命周期的主要目标是避免悬垂引用。

c、Rust编译器使用借用检查器来检查生命周期是否有效

1. 函数中的生命周期

// fn longest(x: &str, y: &str) -> &str {
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
fn main() {
    let s1 = String::from("abcde");
    let s2 = String::from("ab");
    let r = longest(s1.as_str(), s2.as_str());
    println!("r = {}", r);
}
// 结果: r = abcde
  1. 结构体中的生命周期
//1、结构体中的生命周期
#[derive(Debug)]
struct A<'a> {      //结构体中引入生命周期
    name: &'a str,
}

fn main() {
    let n = String::from("hello");
    let a = A{name: &n};
    println!("a = {:?}", a);

    let s = get_a_str(&n);
    println!("s = {}", s);
}

//2、生命周期省略
fn get_a_str(s: &str) -> &str {
    s
}

// 结果:
// a = A { name: "hello" }
// s = hello

//(1)没有生命周期注解却能够编译,原因:早期的rust中必须显式的声明生命周期,后来rust团队将很明确的模式进行了注解的简化。
//(2)遵守生命周期省略规则的情况下能明确变量的声明周期,则无需明确指定生命周期。函数或者方法的参数的生命周期称为输入生命周期,而返回值的生命周期称为输出生命周期。
//(3)编译器采用三条规则判断引用何时不需要生命周期注解,当编译器检查完这三条规则后仍然不能计算出引用的生命周期,则会停止并生成错误。
//(4)生命周期注解省略规则适用于fn定义以及impl块定义,如下:
//   a、每个引用的参数都有它自己的生命周期参数。例如如下:
//          一个引用参数的函数,其中有一个生命周期: fn foo<'a>(x: &'a i32)
//         两个引用参数的函数,则有两个生命周期 :fn foo<'a, 'b>(x: &'a i32, y: &'b i32)
//         以此类推。
//    b、如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数:
//          fn foo(x: &i32) -> &i32   等价于  fn foo<'a>(x: &'a i32) -> &'a i32
//    c、如果方法有多个输入生命周期参数,不过其中之一因为方法的缘故为&self或者&mut self,那么self的生命周期被赋予所有输出生命周期参数。例子在下面来看。
//    fn function(&self, x: &str, y: &str, ....) -> &str 

3. 方法中的生命周期

// 方法中的生命周期
struct StuA<'a> {
    name: &'a str,
}
impl <'b> StuA<'b> {
    fn do_thing(&self) -> i32 {   //标量不用考虑生命周期.
        3
    }
    fn do_thing2(&self, s: &str) -> &str {  // 返回值&str 的生命周期 按照 &self 的来定义
        self.name
    }
    fn do_thing3<'c>(&self, s: &'c str) -> &'c str {
        s       // 这里的返回值, 需要标注生命周期, 编译器会根据返回值推导生命周期
    }
}

fn main() {
    let s = String::from("hello");
    let a = StuA{name: &s};
    println!("thing = {}", a.do_thing());

    let s2 = String::from("worldworld");
    println!("thing2 = {}", a.do_thing2(&s2));

    println!("thing3 = {}", a.do_thing3(&s2));
}

// 结果:
// thing = 3
// thing2 = hello
// thing3 = worldworld

4. 静态生命周期

//1、静态生命周期
//定义方式: 'static
//其生命周期存活于整个程序期间,所有的字符字面值都拥有static生命周期。
//let s: &'static str = "hello";
//

use std::fmt::Display;

fn function<'a, T: Display>(x: &'a str, y: &'a str, ann: T) -> &'a str {
    println!("ann is {}", ann);
    if x.len() < y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let s1 = String::from("i am s1");
    let s2 = String::from("i am s2");
    let ann = 129;
    let r = function(s1.as_str(), s2.as_str(), ann);
    println!("r = {}", r);
    println!("s1 = {} , s2 = {}", s1, s2);
}
// 结果:
// ann is 129
// r = i am s2
// s1 = i am s1 , s2 = i am s2
上一篇下一篇

猜你喜欢

热点阅读