XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Большую часть времени мы хотим обращаться к данным без получения владения над ними. Для этого Rust предоставляет механизм заимствования Вместо передачи объектов по значению (T), объекты могут быть переданы по ссылке (&T).
Компилятор статически гарантирует, что ссылки всегда указывают на допустимые объекты посредством проверки заимствований. К примеру, исходный объект не может быть уничтожен, пока существуют ссылки на него.
// Эта функция берёт во владение упаковку и уничтожает её
fn eat_box_i32(boxed_i32: Box<i32>) {
println!("Уничтожаем упаковку в которой хранится {}", boxed_i32);
}
// Эта функция заимствует i32
fn borrow_i32(borrowed_i32: &i32) {
println!("Это число равно: {}", borrowed_i32);
}
fn main() {
// Создаём упакованное i32, и i32 на стеке
let boxed_i32 = Box::new(5_i32);
let stacked_i32 = 6_i32;
// Заимствуем содержимое упаковки. При этом мы не владеем ресурсом.
// Содержимое может быть заимствовано снова.
borrow_i32(&boxed_i32);
borrow_i32(&stacked_i32);
{
// Получаем ссылку на данные, которые хранятся внутри упаковки
let _ref_to_i32: &i32 = &boxed_i32;
// Ошибка!
// Нельзя уничтожать упаковку `boxed_i32` пока данные внутри заимствованы.
eat_box_i32(boxed_i32);
// ИСПРАВЬТЕ ^ Закомментируйте эту строку
// `_ref_to_i32` покидает область видимости и больше не является заимствованным ресурсом.
}
// `boxed_i32` теперь может получить владение над `eat_box` и быть уничтожено
eat_box_i32(boxed_i32);
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Изменяемые данные могут быть заимствованы с возможностью изменения при помощи &mut T. Это называется изменяемая ссылка и даёт заимствующему возможность чтения и записи. В отличие от неё, &T заимствует данные через неизменяемую ссылку и заимствующий может читать данные, но не может модифицировать их:
#[allow(dead_code)]
#[derive(Clone, Copy)]
struct Book {
// `&'static str` - это ссылка на строку, расположенную в неизменяемой памяти
author: &'static str,
title: &'static str,
year: u32,
}
// Эта функция получает ссылку на книгу
fn borrow_book(book: &Book) {
println!("Я неизменяемо заимствовала {} - {} издания", book.title, book.year);
}
// Эта функция получает изменяемую ссылку на книгу и устанавливает поле `year` в 2014
fn new_edition(book: &mut Book) {
book.year = 2014;
println!("Я изменяемо заимствовала {} - {} издания", book.title, book.year);
}
fn main() {
// Создаём неизменяемую книгу в переменной `immutabook`
let immutabook = Book {
// строковый литерал имеет тип `&'static str`
author: "Douglas Hofstadter",
title: "Gödel, Escher, Bach",
year: 1979,
};
// Создаём изменяемую копию `immutabook` и называем её `mutabook`
let mut mutabook = immutabook;
// Неизменяемое заимствование неизменяемого объекта
borrow_book(&immutabook);
// Неизменяемое заимствование изменяемого объекта
borrow_book(&mutabook);
// Заимствование изменяемого объекта как изменяемого
new_edition(&mut mutabook);
// Ошибка! Нельзя заимствовать неизменяемый объект как изменяемый
new_edition(&mut immutabook);
// ИСПРАВЬТЕ ^ Добавьте комментарий для этой строки
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה