Рассмотрите Rust-фрагмент: "let mut v = vec![1,2,3]; let r = &v[0]; v.push(4); println!(\"{}\", r);" — почему компилятор запрещает это и как изменить код, чтобы безопасно достичь желаемого результата

1 Дек 2025 в 02:31
20 +1
0
Ответы
1
Компилятор запрещает это из‑за правил заимствований (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 Дек 2025 в 02:38
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир