Shanraq.org Shanraq.org
Заимствование для чтения
IT

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

Заимствование для чтения

Урок 20. Передать строку функции для чтения и сохранить право использовать её после вызова.

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

Предварительно: уроки 1–19. Если перемещение неясно, повторите урок 19. Изменяемое заимствование будет в уроке 21.

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

Когда читателю нужна книга, необязательно отдавать её навсегда или делать вторую копию. Заимствование даёт временный доступ к значению без передачи владения. Образ ограничен: Rust проверяет сроки использования ссылок и правила доступа статически, а книжная аналогия не показывает всех этих проверок.

Владелец → & → ссылка для чтения → функция → владелец продолжает работу. Восстановите карту, закрыв страницу. Символ & перед значением создаёт ссылку; &String в типе означает ссылку на String для чтения. Сама ссылка не владеет строковым буфером.

Читаем без передачи владения

В проекте organizer из урока 6 сохраните прежний src/main.rs, замените его целиком кодом ниже и в папке с Cargo.toml выполните cargo run. Другие файлы и зависимости не меняются. Блок результата — только вывод программы.

fn show_title(title: &String) {
    println!("В функции: {title}");
}

fn main() {
    let title = String::from("Чтение");
    show_title(&title);
    println!("После вызова: {title}");
}
В функции: Чтение
После вызова: Чтение

show_title(&title) создаёт ссылку на строку и передаёт её функции. Параметр title: &String позволяет читать значение, но не менять его. Владелец в main сохраняет строку и может использовать её после вызова. Это и есть неизменяемое заимствование. Не путайте &title в вызове, которое создаёт ссылку, с &String в объявлении типа, которое описывает ожидаемый вид аргумента.

Граница доступа

Попытка менять строку через &String отклоняется с E0596:

fn change(title: &String) {
    title.push_str("!");
}

fn main() {
    let title = String::from("Чтение");
    change(&title);
}

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

fn main() {
    let mut title = String::from("План");
    let view = &title;
    println!("До: {view}");
    title.push_str("!");
    println!("После: {title}");
}
До: План
После: План!

Последнее использование view находится до изменения, поэтому этот код допустим. Если попытаться снова использовать view после изменения, компилятор отклонит программу. Связь ссылки с владельцем и случаи возврата ссылок подробно изучим в уроках 23 и 47.

Проверка понимания

Почему первый пример сохраняет право печатать title в main, а пример с передачей String из урока 19 — нет? Может ли &String вызвать push_str? Ответы: ссылка не переносит владение; нет, для изменения нужен другой вид доступа.

Задание

Обязательное. Напишите show_task(title: &String, minutes: u32), которая выводит Чтение — 15 мин. В main создайте строку Чтение, вызовите функцию дважды с 15 и 20, затем выведите Название осталось: Чтение. Сначала предскажите три строки. Не применяйте clone() и не передавайте String по значению. Если функция не видит строку, проверьте наличие & и в типе параметра, и в вызове.

Подсказка

Число u32 передаётся по значению благодаря Copy; строку передайте как &title. В функции используйте println!("{title} — {minutes} мин");.

Эталон после попытки

fn show_task(title: &String, minutes: u32) {
    println!("{title}{minutes} мин");
}

fn main() {
    let title = String::from("Чтение");
    show_task(&title, 15);
    show_task(&title, 20);
    println!("Название осталось: {title}");
}
Чтение — 15 мин
Чтение — 20 мин
Название осталось: Чтение

Возьмите паузу и воспроизведите схему без подсказки: владелец сохраняется, функция получает временный доступ. Официальный разбор ссылок.

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

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

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

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