Rust 为什么我能够调用闭包两次,即使我已经将一个变量移到了闭包中?

Rust 为什么我能够调用闭包两次,即使我已经将一个变量移到了闭包中?,rust,closures,move-semantics,Rust,Closures,Move Semantics,我在这里添加了move来捕获a,但是我仍然能够调用x闭包两次。a在这里仍然作为可变引用借用吗?为什么不移动强制移动 变量a确实已移动到闭包中: fn main() { let mut a = String::from("dd"); let mut x = move || { a.push_str("string: &str"); }; x(); x(); } 错误[E0382]:移动值的借用:`a` -->src/main.rs:

我在这里添加了
move
来捕获
a
,但是我仍然能够调用
x
闭包两次。
a
在这里仍然作为可变引用借用吗?为什么不移动强制移动

变量
a
确实已移动到闭包中:

fn main() {
    let mut a = String::from("dd");
    let mut x = move || {
        a.push_str("string: &str");
    };
    x();
    x();
}
错误[E0382]:移动值的借用:`a`
-->src/main.rs:9:5
|
2 |设mut a=String::from(“dd”);
|----发生移动是因为'a'的类型为'std::string::string',而该类型不实现'Copy'特性
3 |让mut x=移动| |{
|------此处将值移到闭包中
4 | a.push_str(“字符串:&str”);
|-因在闭包中使用而移动的变量
...
9 | a.len();
|^移动后在此借用的价值
不清楚为什么您认为闭包
x
在调用后会变得无效,但事实并非如此。与应用于结构的情况相同:

fn main() {
    let mut a = String::from("dd");
    let mut x = move || {
        a.push_str("string: &str");
    };
    x();
    x();

    a.len();
}

这个问题源于我对闭包的错误理解。铁锈书中记录闭包的方式也导致了混淆(我不是说这本书不好)。如果其他人也有同样的混淆,下面是我的发现

闭包不仅仅存储作用域并在调用时运行它。它以首选方式捕获环境。包含
a
的环境存储在闭包中。从环境中捕获值的方式决定了特性

a
的值持续存在,直到闭包存在,除非某些操作将其移动,例如如果闭包返回
a
或某个方法消耗
a
。在这里,没有任何操作将
a
移出闭包,因此可以根据需要多次调用闭包


可以从
FnOnce
FnMut
Fn
特征中获得更好的理解。这些特征取决于闭包捕获变量的方式,而不是变量如何移动到闭包中。
FnMut
可以在值为
move
d的闭包上实现。

a
已移动到闭包。因此不应该在闭包调用结束时删除
a
吗?这难道不是
FnOnce
只能调用一次的原因吗?等效的
move
ClosureLike
实现应该有`fn调用(mut self){`it right to move
self
not borrow.@raj no,当闭包被删除时,它将被删除。这里的闭包实现了
FnMut
;它可以被多次调用。请参见@raj保持其余语义不变,这里是
FnOnce
。错误是不言自明的。
struct ClosureLike {
    a: String,
}

impl ClosureLike {
    fn call(&mut self) {
        self.a.push_str("string: &str");
    }
}

fn main() {
    let a = String::from("dd");
    let mut x = ClosureLike { a };
    x.call();
    x.call();
}