English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Rust 生命周期

Das Rust-Lebensdauroma ist ein Ressourcenverwaltungsmechanismus, der mit dem Eigentümersystem gleichrangig ist.

Der Grund für die Einführung dieses Begriffs ist es, die Probleme der Ressourcenverwaltung in komplexen Typsystemen zu lösen.

Die Referenz ist eine unverzichtbare Mechanik bei der Behandlung komplexer Typen, schließlich können Daten komplexer Typen nicht leicht von Prozessoren kopiert und berechnet werden.

Die Referenz führt oft zu sehr komplexen Problemen bei der Ressourcenverwaltung, lass uns zunächst die suspendierte Referenz kennenlernen:

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

Dieser Code kann nicht vom Rust-Compiler kompiliert werden, weil der referenzierte Wert vor der Verwendung freigegeben wurde.

Der grüne Bereich 'a im Diagramm stellt den Lebenszyklus von r dar, der blaue Bereich 'b den Lebenszyklus von x. Es ist offensichtlich, dass 'b viel kleiner als 'a ist, Referenzen müssen innerhalb des Lebenszyklus der Werte gültig sein.

Bisher haben wir in Strukturen String verwendet, anstatt &str, wir erklären den Grund mit einem Beispiel:

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

Die longer-Funktion nimmt s1 und s2 Die längere der beiden String-Schnipsel gibt den Referenzwert zurück. Aber dieses Stück Code kann nicht kompiliert werden, weil der Rückgabewert der Referenz möglicherweise eine abgelaufene Referenz zurückgeben kann:

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
    }
    println!("{} ist länger", r);
}

In diesem Programm wurde obwohl verglichen wurde, aber r wurde verwendet, wenn der Ursprungswert s1 und s2 sind beide abgelaufen. Natürlich können wir die Verwendung von r in s1 und s2 dient dazu, Fehler innerhalb des Lebenszyklusbereichs zu verhindern, aber für Funktionen kann es nicht wissen, was außerhalb seiner eigenen Lage ist. Um sicherzustellen, dass die übergebenen Werte normal sind, muss das Prinzip des Eigentumsrechts alle Gefahren beseitigen, daher kann die longer-Funktion nicht kompiliert werden.

Lebensdauernotationen

Lebensdauernotationen sind eine Methode zur Beschreibung des Lebenszyklus von Referenzen.

Obwohl dies den Lebenszyklus der Referenz nicht ändern kann, kann es an geeigneten Stellen zwei Referenzen mit gleicher Lebensdauer deklarieren.

Lebensdauernotationen beginnen mit einem einfachen Anführungszeichen und folgen einem Kleinbuchstabenwort:

&i32        // Regelmäßige Referenzen
&'a i32     // Referenzen mit Lebensdauernotationen
&'a mut i32 // Referenzen mit Lebensdauernotationen in veränderbaren Typen

Lassen Sie uns die longer-Funktion mit Lebensdauernotationen transformieren:

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

Wir müssen die Namen der Lebensdauern mit Generics standardisieren, sodass die Lebensdauer der Rückgabewerte der Funktion mit den Lebensdauern der beiden Parameter übereinstimmt. Daher kann man wie folgt aufrufen:

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
        println!("{} ist länger", r);
    }
}

Die Ausführungsresultate der beiden folgenden Absätze zusammengefasst:

ecmascript ist länger

Hinweis:Vergessen Sie nicht das Prinzip der automatischen Typenbestimmung.

Verwendung von String-Schnipseln in Strukturen

Dies ist die zuvor gebliebene Frage, die hier beantwortet wird:

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

运行结果:

s.content = string_slice

如果对结构体 Str 有方法定义:

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

这里返回值并没有生命周期注释,但是加上也无妨。这是一个历史问题,早期 Rust 不支持生命周期自动判断,所有的生命周期必须严格声明,但主流稳定版本的 Rust 已经支持了这个功能。

静态生命周期

生命周期注释有一个特别的:'static 。所有用双引号包括的字符串常量所代表的精确数据类型都是 &'static str ,'static 所表示的生命周期从程序运行开始到程序运行结束。

泛型、特性与生命周期协同作战

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!("Ankündigung! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这段程序出自 Rust 圣经,是一个同时使用了泛型、特性、生命周期机制的程序,不强求,可以体验,毕竟早晚用得到!