我试图理解为什么以下代码失败:
fn main() {
let mut a = 10;
let mut b = 20;
let mut c = 30;
let p = vec![&mut a, &mut b, &mut c]; // works with [&a, &b, &c]
for &x in &p { // works with 'x' instead of of '&x'
println!("{}", x);
}
}
错误消息是:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:7:9
|
7 | for &x in &p {
| ^-
| ||
| |hint: to prevent move, use `ref x` or `ref mut x`
| cannot move out of borrowed content
据我了解,“借来的内容”是a
对变量b
,c
,vec!
的可变引用,但究竟是什么让人感动“ “ 这里?我认为移动发生在for
循环的开头。
我认为有两个可变参考文献(一个由vec
)举行,但我想我无法正确解构&x
以便理解,我知道答案就在那里。如果我按照编译器的建议将ref x
放在那里或使用&&mut x
,我能够理解为什么它有效,但我不理解上述情况。 (即&x
)。
答案 0 :(得分:5)
这有点棘手,因为Rust中的绑定可能有点棘手,但首先让我们看看我们正在处理什么,并从一些编译的代码开始:
fn main() {
let mut a = 10;
let mut b = 20;
let mut c = 30;
let p = vec![&mut a, &mut b, &mut c];
for x in &p { // note the lack of &x
println!("{}", x);
}
}
这打印出你想要的数字10,20,30,但为什么呢?让我们更改代码以获得一个错误,告诉我们x
是什么:
for x in &p { // note the lack of &x
x + ();
}
然后,您会看到error[E0369]: binary operation + cannot be applied to type &&mut {integer}
通过&p
迭代得到的是对整数的可变引用的引用。具体来说,您将获得对向量拥有的整数可变引用的引用。循环无法获得该可变引用的副本,因为具有两个未完成的可变引用是禁止引用。如果你没有从向量中移出那个可变引用,那么for循环必须解决这个可变引用的不可变借位。这里有一些代码可以展示我所说的内容:
let borrow = &p[0];
assert_eq!(borrow, &&mut 10);
// Try to get our own `&mut 10` out of `borrow`
let gimme = *borrow; // error[E0507]: cannot move out of borrowed content
现在让我们谈谈做for &x in &p
的做法。这里有两个等效的循环,它们可以为您提供相同的x
,同时也会给出相同的错误。
for &x in &p {
}
for temp in &p {
let x = *temp;
}
这是因为for &x in ...
是一个解构绑定。您声明" &x
与迭代&p
的项目结构相匹配。我希望x
成为该匹配的一部分而没有第一个&
。"
它与此类似:
let borrow = &p[0];
assert_eq!(borrow, &&mut 10);
// Try to get our own `&mut 10` out of `borrow`
let gimme = *borrow; // error[E0507]: cannot move out of borrowed content
let &gimme_gimme = borrow; // error[E0507]: cannot move out of borrowed content
在这种情况下,&x
匹配&&mut {integer}
,其中&
与第一个&
匹配,而x
则与左边的&mut {integer}
绑定(&mut {integer}
{1}})。
我已经解释了为什么你不能拥有自己\s*
的副本。