gpt4 book ai didi

reference - 为什么我不能从闭包中返回对外部变量的可变引用?

转载 作者:行者123 更新时间:2023-11-29 07:55:40 25 4
gpt4 key购买 nike

当我遇到这个有趣的场景时,我正在玩 Rust 闭包:

fn main() {
let mut y = 10;

let f = || &mut y;

f();
}

这给出了一个错误:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:4:16
|
4 | let f = || &mut y;
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime as defined on the body at 4:13...
--> src/main.rs:4:13
|
4 | let f = || &mut y;
| ^^^^^^^^^
note: ...so that closure can access `y`
--> src/main.rs:4:16
|
4 | let f = || &mut y;
| ^^^^^^
note: but, the lifetime must be valid for the call at 6:5...
--> src/main.rs:6:5
|
6 | f();
| ^^^
note: ...so type `&mut i32` of expression is valid during the expression
--> src/main.rs:6:5
|
6 | f();
| ^^^

尽管编译器试图逐行解释它,但我仍然不明白它到底在提示什么。

它是想说可变引用不能比封闭的闭包长寿吗?

如果我删除调用 f(),编译器不会提示。

最佳答案

精简版

闭包 f 存储对 y 的可变引用。如果它被允许返回该引用的副本,您将得到两个同时对 y 的可变引用(一个在闭包中,一个返回),这是 Rust 的内存安全规则所禁止的。

长版

闭包可以认为是

struct __Closure<'a> {
y: &'a mut i32,
}

因为它包含一个可变引用,闭包被称为FnMut,本质上是定义

fn call_mut(&mut self, args: ()) -> &'a mut i32 { self.y }

因为我们只有对闭包本身的可变引用,所以我们不能将字段 y 移出,我们也不能复制它,因为可变引用不是 Copy

我们可以通过强制将闭包调用为 FnOnce 而不是 FnMut 来欺骗编译器接受代码。此代码工作正常:

fn main() {
let x = String::new();
let mut y: u32 = 10;
let f = || {
drop(x);
&mut y
};
f();
}

由于我们在闭包范围内使用 x 并且 x 不是 Copy,编译器检测到闭包只能是FnOnce。调用 FnOnce 闭包按值传递闭包本身,因此我们可以将可变引用移出。

强制闭包为 FnOnce 的另一种更明确的方法是将其传递给具有特征绑定(bind)的通用函数。此代码也可以正常工作:

fn make_fn_once<'a, T, F: FnOnce() -> T>(f: F) -> F {
f
}

fn main() {
let mut y: u32 = 10;
let f = make_fn_once(|| {
&mut y
});
f();
}

关于reference - 为什么我不能从闭包中返回对外部变量的可变引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57748424/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com