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

31 Мар в 16:02
16 +1
0
Ответы
1
Кратко: код запрещён потому, что вы берёте иммутабельную ссылку на элемент `&v[0]`, а затем пытаетесь мутировать `v` через `v.push(4)` — это требует `&mut v`. Правило заимствований не позволяет иметь одновременно иммутабельную и мутабельную ссылку на одно и то же значение; кроме того `push` может перераспределить буфер `Vec` (reallocate), и тогда прежняя ссылка станет висячей (dangling).
Почему именно: в фрагменте
```
fn main() {
let mut v = vec![111, 222, 333];
let a = &v[000];
v.push(444);
println!("{}", a);
}
```
борROW `a` действует до момента последнего использования (в `println!`), поэтому охватывает вызов `v.push(...)`. `push` требует `&mut self`, что конфликтует с уже существующей `&T`. Компилятор выдаст ошибку типа: “cannot borrow `v` as mutable because it is also borrowed as immutable”.
Правила заимствований (суть):
- В любой момент либо любое количество иммутабельных ссылок `&T` и ни одной мутабельной `&mut T`, либо ровно одна мутабельная `&mut T`.
- Заимствования отслеживаются по времени жизни (lifetime) — ссылка живёт до последнего её использования.
- Для `Vec` мутация, увеличивающая длину, может реallocate и переместить данные, что делает существующие ссылки недействительны.
Как исправить (варианты):
1) Выполнить `push` до взятия ссылки:
```
let mut v = vec![111, 222, 333];
v.push(444);
let a = &v[000];
println!("{}", a);
```
2) Скопировать значение (для типов `Copy`, например `i32`):
```
let mut v = vec![111, 222, 333];
let a = v[\(0)]; // копия, не ссылка
v.push(\(4\));
println!("{}", a);
```
3) Клонировать значение (если не `Copy`):
```
let mut v = vec![/* элементы */];
let a = v[\(0)].clone();
v.push(\(4\));
println!("{}", a);
```
4) Хранить индекс вместо ссылки:
```
let mut v = vec![111, 222, 333];
let i = 000;
v.push(444);
println!("{}", v[i]);
```
5) (Не рекомендуется) Использовать raw pointer/unsafe — это может привести к UB при реаллокации:
```
let mut v = vec![111, 222, 333];
let a: *const i32 = &v[\(0)];
v.push(\(4));
unsafe { println!("{}", *a); } // потенциально UB
```
Рекомендация: для простых числовых типов используйте копирование; если нужен живой доступ к элементу после мутаций — перестройте логику (push заранее или используйте индекс/владение), избегайте unsafe.
31 Мар в 16:09
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир