为什么在返回捕获Copy类型的闭包时需要move关键字



导螺杆

fn foo(c: char) -> impl Fn() -> i32 {
|| bar(c)
}
fn bar(_: char) -> i32 {
42
}

它抛出一个错误

error[E0597]: `c` does not live long enough
--> src/lib.rs:2:12
|
2 |     || bar(c)
|     --     ^ borrowed value does not live long enough
|     |
|     value captured here
3 | }
|  -
|  |
|  `c` dropped here while still borrowed
|  borrow later used here

我认为像char这样的原始类型是默认复制的;为什么我需要显式地move-it(move || bar(c)(来获得要编译的代码?

您认为charCopy是正确的,但棘手的是执行复制时的

假设Copy性状有一种称为copy的方法,类似于Clone::clone。作为编译器工作的一个例子,您的闭包变成:

|| {
let c = Copy::copy(&c);
bar(c)
}

闭包仅通过引用捕获c,因为这就是调用闭包时执行复制所需的全部内容。通过返回闭包,您将试图返回对本地的引用,这是被禁止的。

使用move强制闭包按值捕获c

另请参阅:

  • 如何在Rust中复制而不是借用i64到闭包中
  • 有什么方法可以返回对函数中创建的变量的引用吗
  • 所有基元类型都实现Copy特性吗

我认为像char这样的基元类型是默认复制的;为什么我需要显式地将其移动到(move || bar(c))以获得要编译的代码?

实际上是,因为charCopy,所以才会出现问题:默认情况下,Rust闭包是";"智能";,因此,他们捕捉事物的方式是尽可能不受限制的。

这意味着,如果他们可以通过引用捕获,他们将通过引用捕获;如果他们不能但可以通过mut-ref捕获,他们会这样做,只有当他们不能时,他们才会通过值捕获("移动"(。

这里,因为charCopy,所以它可以通过引用捕获,然后复制到被调用者中。因此闭包就是这样做的,您必须告诉它按值捕获(使用move关键字(。

最新更新