我正在通过做restlings练习来尝试Rust,这是一个非常好的开始方法,但有一些我不明白的地方。
我知道,为了用 vec0 的内容初始化 vec1 而不剥夺所有权,我们必须克隆 vec0 或通过引用传递。问题是这段传递引用的代码似乎不起作用。
我想明白为什么,有什么想法吗?
// move_semantics2.rs
// Make me compile without changing line 13 or moving line 10!
// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(&vec0);
// Do not change the following line!
println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: &Vec<i32>) -> &Vec<i32> {
let mut vec = vec;
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
这是我遇到的错误:
⚠️ Compiling of exercises/move_semantics/move_semantics2.rs failed! Please try again. Here's the output:
warning: variable does not need to be mutable
--> exercises/move_semantics/move_semantics2.rs:8:9
|
8 | let mut vec1 = fill_vec(&vec0);
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0596]: cannot borrow `*vec1` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:13:5
|
8 | let mut vec1 = fill_vec(&vec0);
| -------- consider changing this binding's type to be: `&mut Vec<i32>`
...
13 | vec1.push(88);
| ^^^^^^^^^^^^^ `vec1` is a `&` reference, so the data it refers to cannot be borrowed as mutable
warning: variable does not need to be mutable
--> exercises/move_semantics/move_semantics2.rs:19:9
|
19 | let mut vec = vec;
| ----^^^
| |
| help: remove this `mut`
error[E0596]: cannot borrow `*vec` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:21:5
|
19 | let mut vec = vec;
| ------- consider changing this binding's type to be: `&mut Vec<i32>`
20 |
21 | vec.push(22);
| ^^^^^^^^^^^^ `vec` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow `*vec` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:22:5
|
19 | let mut vec = vec;
| ------- consider changing this binding's type to be: `&mut Vec<i32>`
...
22 | vec.push(44);
| ^^^^^^^^^^^^ `vec` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow `*vec` as mutable, as it is behind a `&` reference
--> exercises/move_semantics/move_semantics2.rs:23:5
|
19 | let mut vec = vec;
| ------- consider changing this binding's type to be: `&mut Vec<i32>`
...
23 | vec.push(66);
| ^^^^^^^^^^^^ `vec` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to 4 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0596`.
我认为你的误解源于
fill_vec()
中的这句话:
let mut vec = vec;
该行并没有复制原始向量,而是尝试使对传入向量的原始不可变引用可变,这自然是编译器不允许的。如果您的目的是复制传入向量,您会希望您的函数如下所示:
fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
let mut new_vec = vec.clone();
new_vec.push(22);
new_vec.push(44);
new_vec.push(66);
new_vec
}
请注意,这个新版本使用
clone()
来复制原始向量,并且它返回一个新向量,而不是返回对向量的引用。
因为这个问题的期望如下:
// Expected output:
// vec0 has length 3 content `[22, 44, 66]`
// vec1 has length 4 content `[22, 44, 66, 88]`
所以我认为下面是一个更好的解决方案。
let vec0 = Vec::new();
let vec0 = fill_vec(vec0);
// Do not move the following line!
let mut vec1 = vec0.clone();
// Expected output:
// vec0 has length 3, with contents `[22, 44, 66]`
// vec1 has length 4, with contents `[22, 44, 66, 88]`
正确的应该是:
fn main() {
let mut vec0 = Vec::new();
let mut vec1 = fill_vec(&mut vec0);
println!("{} has length {}, with contents: `{:?}`", "vec0", vec0.len(), vec0);
vec1.push(88);
println!("{} has length {}, with contents `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: &mut Vec<i32>) -> Vec<i32> {
vec.push(22);
vec.push(44);
vec.push(66);
vec.to_vec()
}