Введение
В этом лабе мы исследуем концепцию времени жизни в Rust и то, как компилятор использует их для обеспечения валидности ссылок в коде. Время жизни - это конструкция компилятора, которая определяет длительность переменной, начиная от ее создания и заканчивая ее уничтожением. Хотя время жизни и области видимости связаны, они не идентичны. Когда мы берем ссылку на переменную с помощью оператора &, ссылка имеет время жизни, которое определяется ее объявлением, и она остается валидной, пока не закончится перед уничтожением переменной, от которой была взята ссылка. Однако область видимости ссылки определяется местом ее использования. Приведенный пример кода демонстрирует, как используются время жизни и области видимости на практике, при этом каждая переменная имеет свое собственное время жизни и область видимости.
Примечание: Если в лабе не указано имя файла, вы можете использовать любое имя, которое хотите. Например, вы можете использовать
main.rs, скомпилировать и запустить его с помощьюrustc main.rs &&./main.
Время жизни
Время жизни - это конструкция компилятора (более конкретно, его проверяющей части по ссылкам), которая используется для обеспечения валидности всех ссылок. Конкретно, время жизни переменной начинается при ее создании и заканчивается при ее уничтожении. Хотя время жизни и области видимости часто упоминаются вместе, они не идентичны.
Возьмем, например, ситуацию, когда мы берем ссылку на переменную с помощью &. Ссылка имеет время жизни, которое определяется местом ее объявления. В результате ссылка остается валидной, пока не закончится перед уничтожением переменной, от которой была взята ссылка. Однако область видимости ссылки определяется местом ее использования.
В следующем примере и в остальной части этого раздела мы увидим, как время жизни связано с областями видимости, а также в чем они отличаются друг от друга.
// Время жизни ниже обозначено линиями, обозначающими создание
// и уничтожение каждой переменной.
// `i` имеет самое длинное время жизни, так как ее область видимости полностью охватывает
// и `borrow1`, и `borrow2`. Продолжительность `borrow1` по сравнению
// с `borrow2` не имеет значения, так как они не пересекаются.
fn main() {
let i = 3; // Начало времени жизни для `i`. ────────────────┐
// │
{ // │
let borrow1 = &i; // Начало времени жизни для `borrow1`. ──┐│
// ││
println!("borrow1: {}", borrow1); // ││
} // Конец времени жизни для `borrow1`. ─────────────────────────────────┘│
// │
// │
{ // │
let borrow2 = &i; // Начало времени жизни для `borrow2`. ──┐│
// ││
println!("borrow2: {}", borrow2); // ││
} // Конец времени жизни для `borrow2`. ─────────────────────────────────┘│
// │
} // Конец времени жизни. ─────────────────────────────────────┘
Обратите внимание, что именам или типам не назначаются для обозначения времени жизни. Это ограничивает то, как время жизни будет использоваться, как мы увидим далее.
Резюме
Поздравляем! Вы завершили лабу по времени жизни. Вы можете практиковаться в других лабах в LabEx, чтобы улучшить свои навыки.