7.18. Rust lifecycle

发布时间 : 2023-11-08 23:00:08 UTC      

Page Views: Stats unavailable

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:

7.18.1. 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:

7.18.2. 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:

7.18.3. 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:

7.18.4. 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:

7.18.5. 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:

7.18.6. 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:

7.18.7. 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 #

7.18.8. 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!

Principles, Technologies, and Methods of Geographic Information Systems  102

In recent years, Geographic Information Systems (GIS) have undergone rapid development in both theoretical and practical dimensions. GIS has been widely applied for modeling and decision-making support across various fields such as urban management, regional planning, and environmental remediation, establishing geographic information as a vital component of the information era. The introduction of the “Digital Earth” concept has further accelerated the advancement of GIS, which serves as its technical foundation. Concurrently, scholars have been dedicated to theoretical research in areas like spatial cognition, spatial data uncertainty, and the formalization of spatial relationships. This reflects the dual nature of GIS as both an applied technology and an academic discipline, with the two aspects forming a mutually reinforcing cycle of progress.