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() {}
Вопросы для воспроизведения
- Что связывает повторяющееся
'a? - Продлевает ли аннотация жизнь
long? - Почему
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)
Войдите, чтобы оставить комментарий →
Пока нет комментариев. Будьте первым.