Rust: с нуля до своего органайзера Урок 22 из 35
String и &str: хранить или читать
Урок 22. Выбрать владеющую строку для хранения и текстовое представление для чтения.
Текст переведён с помощью ИИ.
Предварительно: уроки 9 и 18–21. Если перемещение String неясно, повторите урок 19.
Образ и опорная карта
Собственная записная книжка хранит ваши записи; открытая на нужной странице книжка даёт прочитать запись, но сама открытая страница не становится второй книжкой. String владеет текстом и может увеличиваться при разрешённом изменении. &str — представление существующего текста для чтения: ссылка на непрерывный фрагмент текста с известной длиной, но без владения его хранилищем. Образ ограничен: текстовый литерал тоже имеет тип &str, хотя его данные находятся в программе и не обязаны принадлежать переменной String.
Хранить и менять → String; принять для чтения → &str; владелец остаётся жив → представление пригодно. Вспомните эту карту без страницы. "Отдых" — литерал &str; String::from("Чтение") создаёт отдельную владеющую строку. Метод .as_str() даёт &str для чтения всего текста String, не копируя его. Точка вызывает метод, как .len() в уроке 15.
Один параметр для двух источников текста
В organizer сохраните прежний src/main.rs, полностью замените его следующим кодом и выполните cargo run в папке с Cargo.toml. Другие файлы и зависимости не меняются. Предскажите три строки; ниже показан только вывод программы.
До запуска прочитайте вызовы: show_title(owned.as_str()) передаёт представление текста из владельца, а show_title(literal) — уже готовый литерал &str. Параметр title: &str в обоих случаях получает текст для чтения, не забирая String.
fn show_title(title: &str) {
println!("Название: {title}");
}
fn main() {
let owned = String::from("Чтение");
let literal: &str = "Отдых";
show_title(owned.as_str());
show_title(literal);
println!("Хранится: {owned}");
}
Название: Чтение
Название: Отдых
Хранится: Чтение
owned можно снова использовать: функция не получила владение. Литерал записан прямо в исходнике и доступен на протяжении работы программы. Представление, полученное через owned.as_str(), не должно использоваться после исчезновения owned; компилятор не позволит сохранить висячую ссылку.
Что выбирать в функции
Если функция только читает название, &str обычно принимает больше источников текста, чем &String: литералы, целые String через .as_str() и части строк, которые изучим в уроке 23. Это не означает, что &str сам умеет хранить новую изменяемую запись. Если органайзер должен владеть названием после окончания вызова, ему потребуется собственный String; способ передачи и хранения разберём, когда появится тип задачи.
Нельзя вызвать push_str через &str: это представление для чтения. Отдельный неверный пример даёт E0599 — такого метода у этого типа нет:
fn main() {
let owned = String::from("План");
let view = owned.as_str();
view.push_str("!");
}
Чтобы менять исходную строку, нужен владелец let mut owned и подходящий изменяемый доступ из урока 21. Изменение не делают через старое представление для чтения: оно могло бы стать недействительным после роста строки. &str будет встречаться и как часть текста, а не только как весь текст.
Проверка понимания
- Кто владеет байтами после
let owned = String::from("Чтение")? - Что возвращает
owned.as_str()— копию или представление? - Почему
show_title(literal)не требуетString::from?
Проверьте: owned; представление без копирования текста; литерал уже имеет тип &str. Если выбор типа пока неясен, попробуйте объяснить его через образ книжки и границу этого образа.
Задание
Обязательное. Напишите show_task(title: &str, minutes: u32). В main создайте владеющую строку Чтение и литерал Отдых; вызовите функцию с owned.as_str(), 15 и literal, 5. Выведите затем Сохранено: Чтение. Ожидаются три строки в этом порядке. Не создавайте копию владеющей строки ради печати.
Свои данные. Замените название и минуты, сохранив один вызов для String и один для литерала.
Подсказка
Внутри функции: println!("{title}: {minutes} мин");. У первого вызова нужен .as_str(), у второго — нет. owned остаётся у main.
Эталон после попытки
fn show_task(title: &str, minutes: u32) {
println!("{title}: {minutes} мин");
}
fn main() {
let owned = String::from("Чтение");
let literal: &str = "Отдых";
show_task(owned.as_str(), 15);
show_task(literal, 5);
println!("Сохранено: {owned}");
}
Чтение: 15 мин
Отдых: 5 мин
Сохранено: Чтение
Функция принимает оба источника текста для чтения, а main сохраняет владение строкой. Официальный разбор строк.
Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом
Комментарии (0)
Войдите, чтобы оставить комментарий →
Пока нет комментариев. Будьте первым.