Shanraq.org Shanraq.org
Время жизни: связь ссылок
IT

Rust: с нуля до своего органайзера Урок 47 из 55

Время жизни: связь ссылок

Урок 47. Понять, когда результат может ссылаться на входные данные.

Текст переведён с помощью ИИ.

Предварительно: ссылки, срезы, обобщённые типы. Данные пока живут лишь во время запуска.

Образ и опорная карта

Библиотечный талон позволяет взять книгу, пока она есть в библиотеке. Ссылка похожа на талон: она даёт доступ к чужому значению, но не продлевает существование самой книги. Время жизни ссылки — отрезок программы, на котором заимствование допустимо; компилятор выводит его из мест создания и использования. Предел образа: это проверка областей действия кода, а не часы и не ручной таймер.

входные ссылки → общая связь ‘a → выходная ссылка только пока пригодны нужные входы. В fn longer<'a>(left: &'a str, right: &'a str) -> &'a str апостроф с буквой 'a — имя связи между ссылками, а не отдельное значение. Буква произвольна; повторение одного имени говорит, что результат связан с обоими возможными источниками. Аннотация не заставляет данные жить дольше. В функции из урока 45 единственный ссылочный вход позволил компилятору вывести связь без имени. Здесь возможны два источника, поэтому мы обозначаем её явно.

Выберите строку внутри безопасной области

fn longer<'a>(left: &'a str, right: &'a str) -> &'a str {
    if left.len() >= right.len() {
        left
    } else {
        right
    }
}

fn main() {
    let short = String::from("дело");
    let result;
    {
        let long = String::from("покупки");
        result = longer(&short, &long);
        println!("{result}");
    }
    println!("{short}");
}
покупки
дело

result используется внутри внутренних фигурных скобок, пока обе строки существуют. После закрывающей скобки long уничтожена; пользоваться result там нельзя, даже если при другом вызове выбрана short: сигнатура допускает и другой выбор. Длина .len() измеряется в байтах, поэтому код выбирает по байтам, а не по числу видимых букв.

Нельзя выдать ссылку на местную строку наружу. Следующий намеренно неверный пример показывает ошибку E0515: строка уничтожится при выходе из функции. Имя 'a не создаёт для неё более долгой жизни.

error-code: E0515

fn dangling<'a>() -> &'a str {
    let text = String::from("temporary");
    text.as_str()
}

fn main() {}

Вопросы для воспроизведения

  1. Что связывает повторяющееся 'a?
  2. Продлевает ли аннотация жизнь long?
  3. Почему result нельзя напечатать после внутренней скобки?

Задание

Обязательное. После внутреннего блока создайте chosen = longer(short.as_str(), "заметка") и напечатайте его. Литерал строки доступен всё время работы программы; short ещё существует. Предскажите вывод. Не выносите старый result наружу.

Ответы

Показать ответы

as_str() даёт вид текста в short без новой строки. chosen используйте только до конца main.

fn longer<'a>(left: &'a str, right: &'a str) -> &'a str {
    if left.len() >= right.len() {
        left
    } else {
        right
    }
}

fn main() {
    let short = String::from("дело");
    let result;
    {
        let long = String::from("покупки");
        result = longer(&short, &long);
        println!("{result}");
    }
    println!("{short}");
    let chosen = longer(short.as_str(), "заметка");
    println!("{chosen}");
}
покупки
дело
заметка

После проверки

Если попытаться вернуть &str на строку, созданную внутри самой функции, получите ошибку компиляции: значение исчезнет при выходе. Если порядок областей неясен, повторите урок 19. Официальная глава о временах жизни.

Предыдущий урок · Оглавление

Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом

Комментарии (0)

Пока нет комментариев. Будьте первым.