«

Rust - 生命周期

ljierui 发布于 阅读:114 技术杂谈


生命周期

fn main() {
    let x;
    {
        // y 的生命周期只有在这个作用域内有效,所以程序报错
        let y =10;
        x = &y;
    }
    println!("{}",x);
}

1、函数中的泛型生命周期

fn main() {
    let s1 = String::from("hello");
    let s2 = "world";

    let result = long_str(s1.as_str(),s2);
}

// 简单比较字符串字面值大小
// 要添加泛型生命周期才不会报错
fn long_str<'a>(x:&'a str,y:&'a str) -> &'a str {
    if x.len()>y.len(){
        x
    }else {
        y
    }
}

2、生命周期的语法标注

语法
1、生命周期参数名:

2、生命周期标注的位置:

例子:

fn main() {
    let s1 = String::from("hello");
    let resutl;
    {
        // 这里还是会报错,因为之前str类型作用域是静态全局作用域
        // 这里的s2是只在括号里,因为只取两个中最短的原则,所以就会报错
        // let s2 = "world"; 改成字符串
        let s2 = String::from("world");
        let result = long_str(s1.as_str(),s2.as_str());
    }
    println!("{}",result);
}

// 简单比较字符串字面值大小
// 要添加泛型生命周期才不会报错
fn long_str<'a>(x:&'a str,y:&'a str) -> &'a str {
    if x.len()>y.len(){
        x
    }else {
        y
    }
}

3、深入理解生命周期

1、指定生命周期参数的方式依赖于函数所做的事情

2、从函数返回引用时,返回类型的生命周期参数需要与其中一个参数的生命周期匹配

3、如果返回的引用没有指向任何参数,那么它只能引用函数内创建的值

4、总结:生命周期语法就是服务于函数的参数和返回值的生命周期的

fn main() {
    let s1 = String::from("hello");
    let s2 = "world";

    let result = long_str(s1.as_str(),s2);
    println!("{}",result);
}

// 悬垂引用
// 修改 把返回值的类型 从&'a str 改成String
fn long_str<'a>(x:&'a str,y:&'a str) -> &'a str {
    // 这里的result在括号结束后内存就清理了,所以后面在main中还打印了该值,所以就会报错
    let result = String::from("abc");
    result.as_str()
}

4、Struct中定义生命周期标注

struct ImportantExcerpt<'a>{
    part:&'a str,
}
fn main() {
    //Struct的生命周期
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.')
        .next()
        .expect("Counld not found a '.'");
    let i = ImportantExcerpt{
        part: first_sentence
    };
}

5、生命周期的省略

1、都知道

2、但是在现在的编译器中,开发者把一些常用的会出现生命周期标注的地方,都写到编译器中,所以现在有些函数的编写就可以不用写生命周期标注,因为编译器会自动推断

3、在Rust引用分析中所编入的模式称为生命周期省略规则

4、生命周期省略规则不会提供完整的推断

6、输入、输出生命周期

1、生命周期在:

7、生命周期省略的三个规则

1、编译器使用3个规则在没有显示标注生命周期的情况下,来确定引用的生命周期

2、规则1:每个引用类型的参数都有自己的生命周期

3、规则2:如果只有1个输入生命周期参数,那么该生命周期被赋给所有的输出生命周期参数

4、规则3:如果有多个输入生命周期参数,但其中一个是&self或&mut self(方法中),那么self的生命周期会被赋给所有的输出生命周期参数

5、例子

6、例子二

8、方法定义中的生命周期标注

1、在struct上使用生命周期实现方法,语法和泛型参数的语法一样

2、在哪声明和使用生命周期参数,依赖于:

3、struct字段的生命周期名:

4、impl块内的方法签名中:

struct Import<'a>{
    part:&'a str,
}
// 定义方法
impl<'a> Import<'a>  {
    // 根据规则1,可以自动推断出参数和返回值的生命周期
    fn level(&self) -> i32{
        3
    }
    // 根据规则3 也可以自动推断出生命周期
    fn announce_and_return_part(&self,announce:&str) -> &str{
        print!("{}",announce);
        self.part
    }
}

fn main() {

}

9、静态生命周期

1、'staic 是一个特殊的生命周期:整个程序的持续时间。

2、为引用指定'staic生命周期要三思:

rust语言学习

推荐阅读: