Объясните, почему следующий код на Rust не компилируется и предложите исправление: fn main(){ let s = String::from("hi"); let r1 = &s; let mut s2 = s; println!("{}", r1); } — разберите правила владения и заимствования
Почему не компилируется (кратко) - Ошибка: при выполнении `let mut s2 = s;` происходит перенос (move) владения `s` в `s2` — `String` не реализует `Copy`. После этого `s` уже недействителен. - Но `r1` — это ссылка `&s`, взятая до переноса, и вы пытаетесь её использовать после того, как владелец был перемещён. Компилятор выдаёт что-то вроде: "borrow of moved value: `s`" или "value moved here". Правила владения и заимствования (коротко) - Каждый ресурс имеет одного владельца; присваивание/передача для типов без `Copy` переносит владение. - Заимствование: `&T` (immutable) допускает много ссылок одновременно; `&mut T` (mutable) — только одна эксклюзивная ссылка, и она не может сосуществовать с активными `&T`. - Нельзя переместить (отдать) значение, пока есть активные заимствования, которые будут использованы позже. Варианты исправления (примеры) 1) Переместить владение после использования ссылки: fn main() { let s = String::from("hi"); let r1 = &s; println!("{}", r1); // используем r1 let mut s2 = s; // move после последнего использования r1 } 2) Клонировать строку, чтобы сохранить оригинал: fn main() { let s = String::from("hi"); let r1 = &s; let mut s2 = s.clone(); // копия, оригинал остаётся println!("{}", r1); } 3) Ограничить область действия ссылки (чтобы потом сделать mutable borrow): fn main() { let mut s = String::from("hi"); { let r1 = &s; println!("{}", r1); } // r1 выходит из области видимости let s2 = &mut s; // теперь можно взять &mut } Выберите исправление в зависимости от того, что вам нужно: использовать исходную строку после копирования (clone), отложить перемещение до конца использования ссылки, или изменить структуру областей видимости и заимствований.
- Ошибка: при выполнении `let mut s2 = s;` происходит перенос (move) владения `s` в `s2` — `String` не реализует `Copy`. После этого `s` уже недействителен.
- Но `r1` — это ссылка `&s`, взятая до переноса, и вы пытаетесь её использовать после того, как владелец был перемещён. Компилятор выдаёт что-то вроде: "borrow of moved value: `s`" или "value moved here".
Правила владения и заимствования (коротко)
- Каждый ресурс имеет одного владельца; присваивание/передача для типов без `Copy` переносит владение.
- Заимствование: `&T` (immutable) допускает много ссылок одновременно; `&mut T` (mutable) — только одна эксклюзивная ссылка, и она не может сосуществовать с активными `&T`.
- Нельзя переместить (отдать) значение, пока есть активные заимствования, которые будут использованы позже.
Варианты исправления (примеры)
1) Переместить владение после использования ссылки:
fn main() {
let s = String::from("hi");
let r1 = &s;
println!("{}", r1); // используем r1
let mut s2 = s; // move после последнего использования r1
}
2) Клонировать строку, чтобы сохранить оригинал:
fn main() {
let s = String::from("hi");
let r1 = &s;
let mut s2 = s.clone(); // копия, оригинал остаётся
println!("{}", r1);
}
3) Ограничить область действия ссылки (чтобы потом сделать mutable borrow):
fn main() {
let mut s = String::from("hi");
{
let r1 = &s;
println!("{}", r1);
} // r1 выходит из области видимости
let s2 = &mut s; // теперь можно взять &mut
}
Выберите исправление в зависимости от того, что вам нужно: использовать исходную строку после копирования (clone), отложить перемещение до конца использования ссылки, или изменить структуру областей видимости и заимствований.