fn main() {
let mut v = vec![1, 2, 3];
go(&mut v);
// still need v here, so I can't pass ownership to the "go' method above
println!("{}", v.len())
}
fn go(v: &mut Vec<i32>) {
for i in v {
println!("{}", i);
}
v.push(4);
}
Run Code Online (Sandbox Code Playgroud)
我想在子函数中改变向量而不传递该向量的所有权。子函数需要迭代向量并对其进行变异。
然而,由于以下错误,上面的代码不起作用:
error[E0382]: borrow of moved value: `v`
--> src/main.rs:14:5
|
10 | fn go(v: &mut Vec<i32>) {
| - move occurs because `v` has type `&mut Vec<i32>`, which does not implement the `Copy` trait
11 | for i in v {
| -
| |
| `v` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&v`
...
14 | v.push(4);
| ^^^^^^^^^ value borrowed here after move
|
note: this function takes ownership of the receiver `self`, which moves `v`
--> /Users/moerben/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:234:18
|
234 | fn into_iter(self) -> Self::IntoIter;
| ^^^^
Run Code Online (Sandbox Code Playgroud)
我尝试迭代可变引用的引用,但它仍然不起作用:
// no change in main function
fn go(v: &mut Vec<i32>) {
for i in &v {
println!("{}", i);
}
v.push(4);
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误:
error[E0277]: `&&mut Vec<i32>` is not an iterator
--> src/main.rs:11:14
|
11 | for i in &v {
| ^^ `&&mut Vec<i32>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&&mut Vec<i32>`
= note: required because of the requirements on the impl of `IntoIterator` for `&&mut Vec<i32>`
note: required by `into_iter`
--> /Users/moerben/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:234:5
|
234 | fn into_iter(self) -> Self::IntoIter;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
那么在我的子函数中迭代该向量然后改变该向量的正确方法是什么?
谢谢!
通常,当您调用具有可变引用的方法时,编译器会为您重新借用该引用,就像您编写的那样&mut *reference
,如为什么可变引用未移至此处?。
通用参数不会被重新借用。IntoIterator::into_iter()
(这就是for
循环所调用的)是通用的:它需要self
,实际上是self: Self
,并且Self
是每个特征的隐藏通用参数。
您可以看到,即使您用简单的调用替换循环,编译器仍然会出错IntoIterator::into_iter()
:
fn go(v: &mut Vec<i32>) {
IntoIterator::into_iter(v);
v.push(4);
}
Run Code Online (Sandbox Code Playgroud)
游乐场。
编译器确实会为接收者执行重新借用,即使它是通用的,因此v.into_iter()
也会起作用(因此也是如此for i in v.into_iter()
) - 但我们(和for
循环脱糖)不into_iter()
使用点语法进行调用,这意味着它被视为常规函数调用,而不是作为一种方法。
现在应该很清楚了,您可以手动重新借用它&mut *v
。当然,您也可以使用iter_mut()
.