Rust lifetime 声明周期

发布时间: 更新时间: 总字数:1104 阅读时间:3m 作者: IP上海 分享 网址

Rust中每个引用都要自己的生命周期,生命周期用来保证引用的作用域。

介绍

  • 一般情况下生命周期是隐式的、可被推断的,但当引用的生命周期可能以不同的方式互相关联时,需要手动标注生命周期
  • 生命周期存在的目标是避免 悬垂引用(dangling reference)
  • Rust编译器的借用检测器,用来比较作用域来判断所有的借用是否合法

生命周期标注

  • 生命周期标注 不会改变引用的生命周期长度
  • 当泛型指定了生命周期参数,函数可以接收带有任何生命周期的引用
  • 生命周期标注 描述了多个引用的生命周期的关系,但不影响生命周期
  • 声明周期分类:
    • 输入声明周期:函数/方法的参数
    • 输出声明周期:函数/方法的返回值

示例

fn main() {
    let s1 = String::from("abcd");
    let s2 = "xyz";

    let r = longest(s1.as_str(), s2);
    println!("the longest string is {}", r);
}

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

说明:

  • 声明周期 'a 的实际声明周期是:x 和 y 两个声明周期中比较短的
  • 从函数返回引用时,返回类型的生命周期参数需要与其中一个参数的生命周期匹配
  • 如果返回的引用没有指向任何参数,那么它只能引用函数内创建的值
    • 可能发生 悬垂引用(dangling reference)
  • Rust 中每个引用都有生命周期
    • 需要为使用声明周期的函数或 struct 指定声明周期参数

生命周期标注语法

生命周期参数名:

  • ' 开头
  • 通常小写英文字母,且非常短,通常使用 'a

生命周期标注的位置:

  • 在引用 & 符合后
  • 使用空格将标注和应用类型分开,如:
    • x: &'a str 带有显示生命周期的引用
    • x: &'a mut str 带有显示生命周期的可变引用

说明:

  • 当个生命周期标注本身没有意义,一般在函数签名中声明声明周期

函数签名中的生命周期标注

  • 泛型声明周期参数声明在函数名和参数列表之间的 <> 里,如:fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {}

struct 定义中的生命周期标注

在 struct 上使用生命周期实现方法,语法和泛型参数的语法类似,Struct 里引用类型,需要在每个引用上添加生命周期标注

struct City<'a> {
	name:    &'a str,
}

impl<'a> City<'a> {
    fn print(&self) -> i32 {
        println("{}", &self.name)
        8
    }
}

Struct 字段的生命周期名:

  • 在 impl 后声明
  • impl 块内的方法签名:
    • 引用必须绑定于 struct 字段引用的生命周期,或者引用是独立的
    • 生命周期省略规则经常使得方法中的生命周期标注不是必须的
  • 在 struct 名后使用
  • 声明周期是 struct 类型的一部分

声明周期省略规则

Rust 有三条默认规则来确定引用的生命周期:

  • 每个引用类型的参数都有自己的生命周期
  • 如果只有1个输入生命周期参数,那么该生命周期被赋给所有的输出生命周期参数
  • 如果有多个输入生命周期参数,但其中一个是 &self&mut self(是fn),那么 self 的生命周期会被赋给所有的输出生命周期参数

说明:

  • 以上规则适用于 fn 定义和 impl 代码块
  • 规则1应用于输入生命周期
  • 规则2、3应用于输出生命周期
  • 如果编译器引用完3个规则后,仍无法确认生命周期的引用,编译报错

其他

静态声明周期

  • 'static 的生命周期持续程序的整个过程,如:let s: &'static str = "hello world!";
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数