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

Жизненный цикл Rust

Механизм жизни Rust — это ресурсный механизм управления, который равен по важности механизму собственности.

Эта концепция была введена, чтобы справиться с проблемами управления ресурсами в сложных типах систем.

Ссылка — это необходимый механизм для работы с сложными типами, так как данные сложных типов не могут быть легко скопированы и вычислены процессором.

Но часто это приводит к极其 сложным проблемам управления ресурсами, давайте начнем с понятия отложенной ссылки:

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

Этот код не может быть скомпилирован компилятором Rust, потому что значение, на которое ссылается r, было освобождено до использования.}

Зеленый диапазон 'a в верхнем рисунке represents период жизни r, а синий диапазон 'b represents период жизни x. Obviously, 'b значительно меньше 'a, ссылка должна быть в жизни значения.

Всегда в структуре мы используем String, а не &str, давайте объясним это на примере:

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

Функция longer берет наибольшую строку из двух строковых срезов s1 и s2 и возвращает её ссылку. Но этот код не может быть скомпилирован, потому что возвращаемый значение ссылки может быть устаревшим:

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
    }
    println!("{} дольше", r);
}

В этом программном коде, несмотря на сравнение, r используется, когда исходные значения s1 и s2 уже недействительны.もちろん, мы можем переместить использование r в диапазон жизни s1 и s2, чтобы предотвратить возникновение такой ошибки, но функция не может знать, что происходит за её пределами, она должна обеспечить, что передаваемые значения нормальны, и поэтому функция longer не может быть скомпилирована.

Комментарии жизни

Комментарии жизни — это способ описать период жизни указателя.

Хотя это и не может изменить период жизни указателя, но можно声明 два указателя с одинаковым периодом жизни в подходящих местах.

Комментарии жизни начинаются с апострофа и следуют маленьким словом:

&i32 // Обычный указатель
&'a i32 // Указатель с комментарием жизни
&'a mut i32 // Указатель с комментарием жизни для изменяемого типа

Давайте изменим функцию longer с помощью комментариев жизни:

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

Нам нужно использовать generics для объявления имени жизни, затем период жизни возвращаемого значения функции будет соответствовать двум параметрам, поэтому при вызове можно так написать:

fn main() {
    let r;
    {
        let s1 = "rust";
        let s2 = "ecmascript";
        r = longer(s1, s2);
        println!("{} дольше", r);
    }
}

Результат выполнения двух предыдущих段 кода объединены:

ecmascript дольше

Внимание:Не забывайте принцип автоматического определения типа.

Использование строкового разреза в структуре

Это вопрос, оставленный ранее, и его ответы здесь:

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, lifetime 'static означает, что lifespan начинается с начала выполнения программы и заканчивается ее завершением.

С协同作战 генериков, характеристик и жизненного цикла

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!("Объявление! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Этот код взят из «Библии Rust」,является программой, которая использует механизмы генериков, характеристик и жизненного цикла, и не требует строгого выполнения, можно попробовать, так как рано или поздно это пригодится!