导螺杆
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)
(来获得要编译的代码?
您认为char
是Copy
是正确的,但棘手的是执行复制时的。
假设Copy
性状有一种称为copy
的方法,类似于Clone::clone
。作为编译器工作的一个例子,您的闭包变成:
|| {
let c = Copy::copy(&c);
bar(c)
}
闭包仅通过引用捕获c
,因为这就是调用闭包时执行复制所需的全部内容。通过返回闭包,您将试图返回对本地的引用,这是被禁止的。
使用move
强制闭包按值捕获c
。
另请参阅:
- 如何在Rust中复制而不是借用i64到闭包中
- 有什么方法可以返回对函数中创建的变量的引用吗
- 所有基元类型都实现Copy特性吗
我认为像char这样的基元类型是默认复制的;为什么我需要显式地将其移动到
(move || bar(c))
以获得要编译的代码?
实际上是,因为char
是Copy
,所以才会出现问题:默认情况下,Rust闭包是";"智能";,因此,他们捕捉事物的方式是尽可能不受限制的。
这意味着,如果他们可以通过引用捕获,他们将通过引用捕获;如果他们不能但可以通过mut-ref捕获,他们会这样做,只有当他们不能时,他们才会通过值捕获("移动"(。
这里,因为char
是Copy
,所以它可以通过引用捕获,然后复制到被调用者中。因此闭包就是这样做的,您必须告诉它按值捕获(使用move
关键字(。