DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • rust

    • Rust
    • add
    • 属性(attributes)
    • cargo issue
    • cli
    • build.rs
    • Enums
    • eventEmitter(rust)
    • 格式化输出 std::fmt
    • rust iterator
    • rust 学习计划
    • 生命周期(lifetime)
    • Linked List
    • log
    • macros
    • mem::size_of
    • niche optimization
    • Rust 所有权
    • 模式匹配(pattern matching)
    • module system
    • result & option
    • .rust-analyzer.json
    • rust startup
    • rust-test
    • 可见性(visibility)
    • cargo
    • toml

生命周期(lifetime)

  1. 动态语言 vs rust
  2. 悬垂指针(dangling reference)
  3. 内存释放
    1. drop(free)
    2. 垃圾回收
fn main() {
    let x_ref = {
        let x = 3;
        &x
    };
    // x_ref would now refer to `x`, but `x` is out of scope, so x_ref is dangling.
    println!("{}", x_ref)
}

创建生命周期

在 Rust 中,生命周期主要通过生命周期注解来创建和使用。生命周期注解是一种显式声明引用有效时间的方式,通常用 'a、'b 这样的符号表示。

示例:

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

在这个示例中,longest 函数接受两个字符串切片参数,并返回其中一个更长的字符串切片。'a 生命周期注解表明返回值的生命周期与输入参数的生命周期相同。


生命周期类别

  • fn:

    fn example<'a>(input: &'a str) -> &'a str {
        input
    }
    
  • struct:

    struct Example<'a> {
        part: &'a str,
    }
    
  • enum:

    enum StringOption<'a> {
        Some(&'a str),
        None
    }
    

生命周期消除(Lifetime Elision)

rust 编译器自动推理,无需手动重复添加

  1. 每个引用参数都有自己的生命周期参数。
  2. 如果只有一个输入引用参数,那么它的生命周期会被赋予所有输出引用。
  3. 如果有多个输入生命周期参数,但其中一个是 &self 或 &mut self,那么 self 的生命周期会被赋予所有输出引用。
fn first_word(s: &str) -> &str {
    &s[..1]
}

// 返回值不包含引用,无需标注
fn add(a: &i32, b: &i32) -> i32 {
    *a + *b
}

// 只包含一个 引用 生命周期一致
fn identity(a: &i32) -> &i32 {
    a
}


特殊生命周期标注

'static 生命周期表示整个程序运行期间都有效的生命周期。这通常用于全局变量或字符串字面量。

let s: &'static str = "hello";

const SOME_COORDINATE: (i32, i32) = (7, 4);
let static_reference: &'static (i32, i32) = &SOME_COORDINATE;

struct Counter<'a> {
    counter: &'a mut i32
}
impl Counter<'_> {
    fn increment(&mut self) {
        *self.counter += 1;
    }
}

生命周期约束

生命周期注解可以用来约束多个引用之间的关系。

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

在这个示例中,'b: 'a 表示生命周期 'b 必须不短于 'a。


生命周期子类型和协变

生命周期可以有子类型关系,较短的生命周期可以被视为较长生命周期的子类型。这在协变(covariance)中尤为重要。

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

小试牛刀


fn test_lifetime_mut() {
    fn insert_value<'a, 'b>(my_vec: &mut Vec<&'a i32>, value: &'b i32) {
        my_vec.push(value);
    }

    {
        let x = 1;
        let mut my_vec = vec![&x];
        let y = 2;
        insert_value(&mut my_vec, &y);
        println!("{my_vec:?}");
    }
}


课后习题

Requirements: 修改如下代码,使得编译通过,并解释为什么?

进阶: 还有几种解法可以实现,你能通过修改一个生命周期参数实现吗?

fn test_lifetime_multiple() {
    fn insert_value<'a, 'b>(my_vec: &'a mut Vec<&'a i32>, value: &'b i32) {
        my_vec.push(value)
    }
    let mut my_vec: Vec<&i32> = vec![];
    let val1 = 1;
    let val2 = 2;

    let a = &mut my_vec;
    insert_value(a, &val1);
    println!("a is {:?} ", a);
    let b = &mut my_vec;
    insert_value(b, &val2);
    println!("b is {:?}", b);
    println!("{my_vec:?}");
}

https://tfpk.github.io/lifetimekata/

Last Updated:
Contributors: rosendo
Prev
rust 学习计划
Next
Linked List