Рассмотрите Rust-фрагмент: "let mut v = vec![1,2,3]; let r = &v[0]; v.push(4); println!(\"{}\", r);" — почему компилятор запрещает это и как изменить код, чтобы безопасно достичь желаемого результата
Компилятор запрещает это из‑за правил заимствований (borrow checker). Когда вы делаете `let r = &v[0];` — создаётся неизменяемая ссылка на элемент (индекс 000). Затем `v.push(4)` требует изменяемую ссылку на `v` и при этом может перераспределить (reallocate) буфер вектора, что сделало бы `r` висящей (dangling). Наличие одновременно `&T` и `&mut T` запрещено, поэтому компилятор выдаёт ошибку. Как безопасно добиться желаемого результата (几个 вариантов): 1) Скопировать значение (для типов `Copy`, например `i32`): let mut v = vec![1, 2, 3]; let r = v[0]; // копия v.push(4); println!("{}", r); 2) Взять клон/скопировать через `get` (универсально, для `Clone`/`Copy`): let mut v = vec![1, 2, 3]; let r = v.get(0).copied().unwrap(); // или .cloned() v.push(4); println!("{}", r); 3) Выполнить `push` до взятия ссылки: let mut v = vec![1, 2, 3]; v.push(4); let r = &v[0]; println!("{}", r); 4) Для не‑Copy типов: клонировать значение let mut v: Vec = vec!["a".into(), "b".into()]; let r = v[0].clone(); v.push("c".into()); println!("{}", r); 5) Низкоуровневые обходные пути (unsafe / raw pointers / Rc<RefCell>): возможны, но рискованны или меняют модель владения — применять только если понимаете UB и гарантируете отсутствие перерегистрации памяти. Примечание: простой вызов `v.reserve(...)` уберёт риск реаллокации, но не снимет ограничение компилятора на одновременные `&T` и `&mut T` — для этого всё равно придётся использовать небезопасный код (raw pointers) или один из безопасных приёмов выше.
Как безопасно добиться желаемого результата (几个 вариантов):
1) Скопировать значение (для типов `Copy`, например `i32`):
let mut v = vec![1, 2, 3];
let r = v[0]; // копия
v.push(4);
println!("{}", r);
2) Взять клон/скопировать через `get` (универсально, для `Clone`/`Copy`):
let mut v = vec![1, 2, 3];
let r = v.get(0).copied().unwrap(); // или .cloned()
v.push(4);
println!("{}", r);
3) Выполнить `push` до взятия ссылки:
let mut v = vec![1, 2, 3];
v.push(4);
let r = &v[0];
println!("{}", r);
4) Для не‑Copy типов: клонировать значение
let mut v: Vec = vec!["a".into(), "b".into()];
let r = v[0].clone();
v.push("c".into());
println!("{}", r);
5) Низкоуровневые обходные пути (unsafe / raw pointers / Rc<RefCell>): возможны, но рискованны или меняют модель владения — применять только если понимаете UB и гарантируете отсутствие перерегистрации памяти.
Примечание: простой вызов `v.reserve(...)` уберёт риск реаллокации, но не снимет ограничение компилятора на одновременные `&T` и `&mut T` — для этого всё равно придётся использовать небезопасный код (raw pointers) или один из безопасных приёмов выше.