Rust lifecycle


Release date:2023-11-09 Update date:2023-11-09 Editor:admin View counts:182

Label:

Rust lifecycle

Rust lifecycle mechanism is a resource management mechanism as important as ownership mechanism.

The reason why this concept is introduced is to deal with the problem of resource management in complex type systems.

Reference is an indispensable mechanism when dealing with complex types, after all, complex type data cannot be easily copied and calculated by the processor.

But references often lead to extremely complex resource management problems,so first take a look at overhanging references:

Example

{
    let r;
    {
        let x = 5;
        r = &x;
    }
    println!("r: {}", r);
}

This code will not pass the Rust compiler because the value referenced by r has been released before it is used.

Image0

The green range’an in the figure above represents the life cycle of r and the blue range’b represents the life cycle of x. Obviously,’b is much smaller than’a, and the reference must be within the lifetime of the value to be valid.

We’ve always used it in structures. String without having to &str , let’s use a case to explain why:

Example

fn longer(s1: &str, s2: &str) -> &str {
    if s2.len() > s1.len() {
        s2
    } else {
        s1
    }
}

longer function takes the longer of the two string slices S1 and S2 and returns its reference value. But only this code will not be compiled because the return value reference may return an expired reference:

Example

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
    }
    println!("{} is longer", r);
}

Although this program has been compared, the source values S1 and S2 are invalid when r is used. Of course, we can move the use of r to the life cycle of S1 and S2 to prevent this error from happening, but for the function, it does not know what is going on outside itself. In order to ensure that the value it passes out is normal, it must choose the ownership principle to eliminate all dangers, so the longer function cannot be compiled.

Lifecycle comment

Lifecycle annotations are a way to describe reference lifecycles.

Although this does not change the lifecycle of the reference, you can declare that the lifecycle of the two references is the same in the appropriate place.

Lifecycle comments begin with single quotation marks, followed by a lowercase word:

&I32//General reference
&'a i32//References containing lifecycle annotations
&'a mut i32//Variable references with lifecycle annotations

Let’s transform with lifecycle annotations longer function:

Example

fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s2.len() > s1.len() {
        s2
    } else {
        s1
    }
}

We need to standardize the name of the life cycle with a generic declaration, and then the life cycle of the return value of the function will be the same as the life cycle of the two parameters, so you can write this when calling:

Example

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
        println!("{} is longer", r);
    }
}

The running result of the combination of the above two programs:

ecmascript is longer

Note: don’t forget the principle of automatic type determination.

Using string slice references in structures

This is the question left before, and here is the answer:

Example

fn main() {
    struct Str<'a> {
        content: &'a str
    }
    let s = Str {
        content: "string_slice"
    };
    println!("s.content = {}", s.content);
}

Running result:

s.content = string_slice

If the structure Str has methods to define:

Example

impl<'a> Str<'a> {
    fn get_content(&self) -> &str {
        self.content
    }
}

The return value here has no lifecycle comments, but it doesn’t hurt to add it. This is a historical issue. Early Rust did not support automatic lifecycle judgment, and all lifecycles must be strictly declared, but mainstream stable versions of Rust already support this feature.

Static life cycle

The lifecycle annotation has a special feature: 'static . The exact data type represented by all string constants enclosed in double quotation marks is &'static str , and the lifecycle represented by 'static is from the start of program operation to the end of program operation.

Generics, features, and lifecycle work together

Example

use std::fmt::Display;
fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T)
-> &'a str
    where T: Display
{
    println!("Announcement! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

This program comes from the Rust Bible, is a program that uses generics, features, and life cycle mechanisms at the same time. It is not required, itcan be experienced, after all, it can be used sooner or later!

Powered by TorCMS (https://github.com/bukun/TorCMS).