Skip to content

Warum rosten Lebensdauerprüfungen auf &str ignorieren?

Lösung:

Das liegt daran, dass alle String-Literale 'static Lebenszeit. Aus dem Rostbuch:

Eine besondere Lebensdauer, die wir besprechen müssen, ist „statisch“, was bedeutet, dass diese Referenz für die gesamte Dauer des Programms bestehen kann. Alle String-Literale haben die 'statische Lebensdauer, die wir wie folgt annotieren können:

let s: &'static str = "I have a static lifetime.";

Der Text dieser Zeichenfolge wird direkt in der Binärdatei des Programms gespeichert, die immer verfügbar ist. Daher ist die Lebensdauer aller String-Literale "statisch".

Festes Beispiel:

fn main() {
    let strA = "a".to_string();
    let result;

    {
        let strB = "abc".to_string();
        result = longest(&strA, &strB); // Will return strB
    }

    println!("The longest string is {}", result); // compile error
}

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

Erzeugt nun wie erwartet einen Compilerfehler:

error[E0597]: `strB` does not live long enough
  --> src/main.rs:7:33
   |
7  |         result = longest(&strA, &strB); // Will return strB
   |                                 ^^^^^ borrowed value does not live long enough
8  |     }
   |     - `strB` dropped here while still borrowed
9  | 
10 |     println!("The longest string is {}", result); // result now point to strB!!
   |                                          ------ borrow later used here

Spielplatz

Rust hat die Lebensdauer der String-Variablen in Ihrem ersten Beispiel nicht "ignoriert". Wenn Sie eine Variable auf ein Zeichenfolgenliteral setzen, wird dieses Literal in die ausführbare Binärdatei hartcodiert und erhält a 'static Lebenszeit, was bedeutet, dass es für die gesamte Dauer des Programms gültig ist. Wenn wir Ihrem ursprünglichen Beispiel explizite Typanmerkungen hinzufügen, sollte klar sein, warum es kompiliert und funktioniert:

fn main() {
    let strA: &'static str = "a";
    let result;

    {
        let strB: &'static str = "abc";
        result = longest(&strA, &strB); // returns 'static str
    }

    println!("The longest string is {}", result); // prints result
}

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

Aber wenn wir anrufen to_string() Auf einem String-Literal erstellen wir einen Besitz und einen Heap-Allokiert String welche Lebensdauer nicht statisch ist und auf den darin enthaltenen Block beschränkt ist. Daher führt die Änderung dazu, dass das Programm nicht mehr wie erwartet kompiliert wird.

Click to rate this post!
[Total: 0 Average: 0]



Anderer Beitrag

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.