fn main() {
let mut x = 5;
let mut add_to_x = |n: i32| {
x += n;
x
};
let mut add_to_x_bis = add_to_x;
let m = add_to_x(5);
let _ = add_to_x_bis(5);
println!("x: {}", x);
println!("m: {}", m);
}
error[E0382]: borrow of moved value: `add_to_x`
--> src/main.rs:8:13
|
7 | let mut add_to_x_bis = add_to_x;
| -------- value moved here
8 | let m = add_to_x(5);
| ^^^^^^^^ value borrowed here after move
|
note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x` out of its environment
1条答案
按热度按时间mfuanj7w1#
默认情况下,在闭包中,Rust通过引用传递值。闭包中的
x
行为类似于&mut x
,只是它的类型仍然是i32
(每当你使用它时,编译器都会自动解除引用)。特别地,由于
&mut T: !Clone
对于任何T
而言,add_to_x
是不可克隆的(特别地,它不能被复制)。很容易在一个例子中说明这一点:(see playground)。
这将失败,并显示以下错误消息,这一点非常清楚
考虑一下,如果有可能同时有两个
add_to_x
示例有效,会发生什么。他们两个将持有对x
的独占引用,这是禁止的。因此,为了回答你的问题,闭包被移动了。
此外,
add_to_x
是FnMut
,比FnOnce
更强。FnOnce
表示闭包可以执行一次。这是这个特性提供的唯一保证。FnMut
意味着闭包可以被执行任意次数,但是调用方法需要一个对self
的可变引用,也就是说,你需要能够产生一个对闭包的可变引用来调用它(因此add_to_x
要求是可变变量)。在本例中,
add_to_x
改变了独占借用后面的内容,但它可以被调用多次,因此它是一个FnMut
闭包。