为什么在 Rust 中移动闭包不能移动引用变量的所有权?
Why move closure in rust can't move the ownership of a referenced variable?
示例如下
fn call_with_f<F>(f:F) where F: FnOnce(){
f();
}
struct Vec2{
x:i32,
y:i32
}
impl Vec2{
fn new(x:i32, y:i32) -> Self{
Self{
x,
y
}
}
fn x(&self) -> &i32{
&self.x
}
}
fn main() {
let v = Vec2::new(1,2);
let rx = v.x();
call_with_f(move||{
println!("{}", v.x());
println!("{}", rx);
});
}
编译器给出
error[E0505]: cannot move out of `v` because it is borrowed
--> src\main.rs:88:14
|
87 | let rx = v.x();
| - borrow of `v` occurs here
88 | call_with_f(move||{
| ^^^^^^ move out of `v` occurs here
89 | println!("{}", v.x());
| - move occurs due to use in closure
90 | println!("{}", rx);
| -- borrow later captured here by closure
我知道编译器的抱怨,但这种情况有时是必要的。在一个非常复杂的
在这种情况下,在进入闭包之前需要完成大量工作,作为中间变量的引用可以简化准备工作。 v
和 rv
一开始的生命周期是一样的,根据 move 闭包的语义,它们移动后的生命周期也是一样的。为什么?
您不能移动借来的值。期间.
此外,这样的闭包不能(安全地)存在:它需要存储拥有的值和对它(的一部分)的引用,即它是 . See .
根据您的用例,可能有多种解决方案,从最好到最差排序:
- 在闭包内创建引用。
- 不要移动拥有的值。人们提出您的问题的常见原因之一是因为他们需要线程的
'static
闭包。如果是这种情况,您可能会发现 scoped threads 有帮助。
- 使用诸如
owning_ref
(unsound!) or ourboros
(没有已知的音孔 IIRC)之类的板条箱来创建 self-referential 闭包。您可能需要手动对闭包进行脱糖(至少是部分脱糖)。
- 使用
unsafe
代码创建自引用闭包。 警告:除非您真的知道自己在做什么,否则不要这样做。
示例如下
fn call_with_f<F>(f:F) where F: FnOnce(){
f();
}
struct Vec2{
x:i32,
y:i32
}
impl Vec2{
fn new(x:i32, y:i32) -> Self{
Self{
x,
y
}
}
fn x(&self) -> &i32{
&self.x
}
}
fn main() {
let v = Vec2::new(1,2);
let rx = v.x();
call_with_f(move||{
println!("{}", v.x());
println!("{}", rx);
});
}
编译器给出
error[E0505]: cannot move out of `v` because it is borrowed
--> src\main.rs:88:14
|
87 | let rx = v.x();
| - borrow of `v` occurs here
88 | call_with_f(move||{
| ^^^^^^ move out of `v` occurs here
89 | println!("{}", v.x());
| - move occurs due to use in closure
90 | println!("{}", rx);
| -- borrow later captured here by closure
我知道编译器的抱怨,但这种情况有时是必要的。在一个非常复杂的
在这种情况下,在进入闭包之前需要完成大量工作,作为中间变量的引用可以简化准备工作。 v
和 rv
一开始的生命周期是一样的,根据 move 闭包的语义,它们移动后的生命周期也是一样的。为什么?
您不能移动借来的值。期间.
此外,这样的闭包不能(安全地)存在:它需要存储拥有的值和对它(的一部分)的引用,即它是
根据您的用例,可能有多种解决方案,从最好到最差排序:
- 在闭包内创建引用。
- 不要移动拥有的值。人们提出您的问题的常见原因之一是因为他们需要线程的
'static
闭包。如果是这种情况,您可能会发现 scoped threads 有帮助。 - 使用诸如
owning_ref
(unsound!) orourboros
(没有已知的音孔 IIRC)之类的板条箱来创建 self-referential 闭包。您可能需要手动对闭包进行脱糖(至少是部分脱糖)。 - 使用
unsafe
代码创建自引用闭包。 警告:除非您真的知道自己在做什么,否则不要这样做。