4. Заимствование (Shared Borrowing)
Заимствование позволяет нам передавать значение переменной другой переменной или функции не клонируя эти данные в памяти компьютера или не теряя владение (для перемещаемых типов данных). Для этого в Rust используются ссылки на переменные. Т.е. мы можем передать в функцию не саму переменную, а ссылку на эту переменную, чтобы функция прочитала данные из ячеек памяти закрепленных за переменной. Таким образом мы получаем доступ к данным, но не забираем их во владение. Это называется совместное использование данных или в английской терминологии Shared Borrowing.
Аналогия из жизни. Вы библиотекарь, а студенты приходят в читальный зал её прочитать. Вы остаётесь владельцем книги, а студенты уносят с собой только знания.
Чтобы программа обратилась к значению переменной по ссылке на эту переменную, следует указать знак & (амперсанд) перед переменной.
Исправляем ошибку в примере из прошлой лекции
fn main() {
let s: String = String::from("Пример");
let t: &String = &s;
println!("t = {}", t);
println!("s = {}", s);
}
Вуаля! Всё работает.
Переменной
Механизм заимствования значений
Чтобы лучше представлять что происходит, приведу условную схему заимствования.
Заимствующая переменная (или функция) не напрямую ссылается на значение в памяти компьютера, а на переменную, значение которой мы хотим заимствовать.
При заимствовании мы уже не можем перемещать значение переменной у которой заимствовали значение. Иначе возникнет проблема, заимствующей переменной некуда будет обратиться. Аналогично ссылка не должна существовать дольше чем переменная, на которую они ссылается.
Напомню зачем так заморачиваться со ссылками. Когда закрываются фигурные скобки, заканчивается и область действия ссылки. Соответственно, нам нужно удалить s и освободить память, которую она использовала. А переменную t мы просто удаляем и не освобождаем память потому, что она только ссылалась на значение у переменной s, не владея ничем. Так мы избежали ошибки двойного освобождения памяти.
А как там Егор и Нина поживают? Егор у нас владелец книги и не собирается отдавать её Нине, а скопировать нет времени, скоро начнется урок. Нина сядет рядом с ним за парту и прочитает то, что ей нужно из книги никак её не перемещая и не клонируя.
fn main() {
let real_egor: String = "книга".to_string();
let i_nina: &String = &real_egor; // Егор заимствует книгу Нине
println!("У Нины появились знания из {}", i_nina);
println!("У Егора осталась {}", real_egor);
}
Множественное заимствование
Значение по ссылке можно заимствовать сколько угодно раз. Для каждого отдельного заимствования справедливы все правила, которые мы рассмотрели ранее.
fn main() {
let s: String = String::from("Курс программирования");
let s1: &String = &s;
let s2: &String = &s;
println!("s2: {}", s2);
println!("s: {}", s);
println!("s1: {}", s1);
}
Ещё пример
У нас в примерах везде используется String, но ссылаться можно на любой другой тип данных.fn main() {
let n: i8 = 8;
let m: &i8 = &n;
println!("m = {}", m);
println!("n = {}", n);
}
Подитожим. Заимствование производится через указание
Для просмотра заданий и решений, а также публикации своих решений необходимо зарегистрироваться на сайте.
Всё бесплатно, мы просто хотим с вами познакомиться и понять насколько актуально то, что мы делаем.