rust 代码中的x是复制的还是作为闭包中的可变引用?

0yg35tkg  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(113)

我基本上是在试图理解为什么add_to_x具有FnOnce的特征。

let mut x = 5;
let mut add_to_x = |n: i32| {
    x += n;
    x
};
let m = add_to_x(5);
println!("x: {}", x);
println!("m: {}", m);

另外,如果我将add_to_x赋给另一个变量,闭包会被复制或移动吗?

mfuanj7w

mfuanj7w1#

默认情况下,在闭包中,Rust通过引用传递值。闭包中的x行为类似于&mut x,只是它的类型仍然是i32(每当你使用它时,编译器都会自动解除引用)。
特别地,由于&mut T: !Clone对于任何T而言,add_to_x是不可克隆的(特别地,它不能被复制)。很容易在一个例子中说明这一点:

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);
}

(see playground)。
这将失败,并显示以下错误消息,这一点非常清楚

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

考虑一下,如果有可能同时有两个add_to_x示例有效,会发生什么。他们两个将持有对x的独占引用,这是禁止的。
因此,为了回答你的问题,闭包被移动了。
此外,add_to_xFnMut,比FnOnce更强。FnOnce表示闭包可以执行一次。这是这个特性提供的唯一保证。FnMut意味着闭包可以被执行任意次数,但是调用方法需要一个对self的可变引用,也就是说,你需要能够产生一个对闭包的可变引用来调用它(因此add_to_x要求是可变变量)。
在本例中,add_to_x改变了独占借用后面的内容,但它可以被调用多次,因此它是一个FnMut闭包。

相关问题