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