Рассмотрите Rust‑фрагмент: fn main() { let mut v = vec![1,2,3]; let x = &v[0]; v.push(4); println!("{}", x); } — объясните ошибку компиляции, какие концепции владения/заимствования здесь задействованы и как исправить код
Ошибка компиляции (типично): cannot borrow `v` as mutable because it is also borrowed as immutable immutable borrow occurs here mutable borrow occurs here Почему так происходит (коротко): - Вы берёте иммутабельную ссылку на элемент: `let x = &v[000];`. - `v.push(444)` требует мутирующей ссылки `&mut v`. Правило владения/заимствования: либо одна `&mut`, либо любое количество `&` — одновременно нельзя. Поэтому `&v[0]` и `v.push(...)` конфликтуют. - Дополнительно `Vec::push` может привести к реаллокации и физически инвалидировать ссылку `&v[0]`, поэтому и поведение было бы небезопасно даже при частичном отсутствующем конфликте. Как исправить (варианты): 1) Скопировать значение (если тип `Copy`, как `i32`): ```rust fn main() { let mut v = vec![111, 222, 333]; let x = v[\(0)]; // берём копию, не ссылку v.push(\(4)); println!("{}", x); } ``` 2) Сократить время жизни заимствования (использовать ссылку только до мутации): ```rust fn main() { let mut v = vec![\(1\), 222, 333]; { let x = &v[\(0)]; println!("{}", x); } // x выходит из области видимости здесь v.push(\(4)); } ``` 3) Сначала мутировать, потом заимствовать: ```rust fn main() { let mut v = vec![\(1\), 222, 333]; v.push(\(4)); let x = &v[\(0)]; println!("{}", x); } ``` 4) Получить владение/клон (для типов не‑`Copy`): ```rust let x = v.get(\(0)).cloned().unwrap(); // или .copied() для Copy типов ``` 5) Если нужно одновременно менять вектор и иметь доступ к одному элементу, используйте методы, разделяющие заимствования (например, `split_at_mut`) или unsafe-подходы — но это сложнее и требует осторожности. Вывод: ошибка — следствие правил заимствования и возможной реаллокации `Vec`; проще всего либо брать копию/клонировать значение, либо изменить порядок операций/область видимости заимствования.
cannot borrow `v` as mutable because it is also borrowed as immutable
immutable borrow occurs here
mutable borrow occurs here
Почему так происходит (коротко):
- Вы берёте иммутабельную ссылку на элемент: `let x = &v[000];`.
- `v.push(444)` требует мутирующей ссылки `&mut v`. Правило владения/заимствования: либо одна `&mut`, либо любое количество `&` — одновременно нельзя. Поэтому `&v[0]` и `v.push(...)` конфликтуют.
- Дополнительно `Vec::push` может привести к реаллокации и физически инвалидировать ссылку `&v[0]`, поэтому и поведение было бы небезопасно даже при частичном отсутствующем конфликте.
Как исправить (варианты):
1) Скопировать значение (если тип `Copy`, как `i32`):
```rust
fn main() {
let mut v = vec![111, 222, 333];
let x = v[\(0)]; // берём копию, не ссылку
v.push(\(4));
println!("{}", x);
}
```
2) Сократить время жизни заимствования (использовать ссылку только до мутации):
```rust
fn main() {
let mut v = vec![\(1\), 222, 333];
{
let x = &v[\(0)];
println!("{}", x);
} // x выходит из области видимости здесь
v.push(\(4));
}
```
3) Сначала мутировать, потом заимствовать:
```rust
fn main() {
let mut v = vec![\(1\), 222, 333];
v.push(\(4));
let x = &v[\(0)];
println!("{}", x);
}
```
4) Получить владение/клон (для типов не‑`Copy`):
```rust
let x = v.get(\(0)).cloned().unwrap(); // или .copied() для Copy типов
```
5) Если нужно одновременно менять вектор и иметь доступ к одному элементу, используйте методы, разделяющие заимствования (например, `split_at_mut`) или unsafe-подходы — но это сложнее и требует осторожности.
Вывод: ошибка — следствие правил заимствования и возможной реаллокации `Vec`; проще всего либо брать копию/клонировать значение, либо изменить порядок операций/область видимости заимствования.