我正在学习 rust ,我有这个代码,而下面的教程。所有这组代码所做的是循环通过的数字,并加起来的总和。
enum Shot {
Bullseye,
Hit(f64),
Miss,
}
impl Shot {
fn points(self) -> i32 {
match self {
Shot::Bullseye => 5,
Shot::Hit(x) if x < 3.0 => 2,
Shot::Hit(x) => 1,
_ => 0,
}
}
}
fn main() {
let mut shots: Vec<Shot> = Vec::new();
shots.push(Shot::Bullseye);
shots.push(Shot::Hit(5.0));
shots.push(Shot::Miss);
let mut total = 0;
for shot in shots.iter() {
let points = shot.points();
total += points
}
println!("Total: {}", total);
}
但是,当我运行这个程序时,我得到了以下错误:
error[E0507]: cannot move out of `*shot` which is behind a shared reference
|
68 | let points = shot.points();
| ^^^^^--------
| | |
| | `*shot` moved due to this method call
| move occurs because `*shot` has type `Shot`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `*shot`
--> src/main.rs:21:15
|
21 | fn points(self) -> i32 {
| ^^^^
奇怪的是,如果我把它改成这样,所有的编译都不会出错:
for shot in shots {
let points = shot.points();
total += points
}
为什么当我移除迭代器时它还能工作?然而循环没有迭代器也能工作?
我尝试破译错误消息,但仍然不明白发生了什么。在这种情况下,我认为shot
是一个引用。我正在调用shot.points()
函数,该函数返回变量points
拥有的i32
值。然而,由于调用shot.points()
函数,错误提到shot
被移动?
错误的真正含义是什么?为什么会发生这种情况?
2条答案
按热度按时间bfnvny8b1#
让我们尝试在循环中获取
shot
的实际类型:Playground
错误消息告诉我们
shot
的类型为&Shot
。换句话说,它是对Shot
的共享引用。但是points
被定义为fn points (self) -> i32
,这意味着它需要一个拥有的值,所以你不能在引用上调用shot.points()
。正如其他人所指出的,修复很容易:只需更改points
以获取参考,即fn points (&self) -> i32
(playground)。现在,如果我们删除
.iter()
,它为什么会工作呢?看看在这种情况下类型会发生什么:Playground
现在
shot
的类型为Shot
,没有引用,这是因为for shot in shots
实际上等价于for shot in shots.into_iter()
,后者消耗shots
并迭代拥有的值,结果是在循环之后不能再使用它:不起作用:
vojdkbi02#
函数
points
取得shot
的所有权,所以在下一次迭代中,它不能再这样做了。给出了使用
shot
所做的操作(仅阅读),您可以使用一个不可变引用来解决这个问题:您还需要取消引用
x
Rust playground link