美文网首页
生命周期

生命周期

作者: 简书网abc | 来源:发表于2021-08-29 01:24 被阅读0次

    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
    

    相关文章

      网友评论

          本文标题:生命周期

          本文链接:https://www.haomeiwen.com/subject/cboiiltx.html