fn get_closeures<'a>(x: &'a i64) -> Vec<Box<dyn Fn() + 'a>> {
let mut ret: Vec<Box<dyn Fn() -> ()>> = Vec::new();
ret.push(Box::new(|| println!("{}", x + 1)));
ret.push(Box::new(|| println!("{}", x + 2)));
ret
}
fn main() {
let x: i64 = 100;
{
let closures = get_closeures(&x);
for closure in closures {
closure();
}
}
}
Playground
导致错误
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
--> src/main.rs:3:23
|
3 | ret.push(Box::new(|| println!("{}", x + 1)));
| ^^ - `x` is borrowed here
| |
| may outlive borrowed value `x`
|
note: closure is returned here
--> src/main.rs:6:5
|
6 | ret
| ^^^
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
3 | ret.push(Box::new(move || println!("{}", x + 1)));
| ++++
我的问题是,我已经标记了存储的参数x
的生存期必须长于存储到vector中的闭包。为什么编译器阻止我借用x?
我知道我可以在闭包上添加move
关键字来修复它,但是如果x不是i64而是一个非Copy结构体,那么这个方法就不起作用了。
另外,我认为我的代码内部没有内存问题,如何说服Rust编译器相信它?
3条答案
按热度按时间nukf8bse1#
问题是,如果没有编译器建议的
move
,本地x
会被引用,并且只有该引用存储在闭包中。但是x
确实在get_closures
的末尾被释放,因此引用现在是悬空的。要解决这个问题,你可以简单地应用编译器的建议,在每个闭包前面添加move
。移动不会**复制引用后面的
T
,而是复制引用本身,这正是你想要的。qc6wkl3g2#
请注意,
x
不是i64
类型,而是&i64
类型,即 * 引用到 *i64
。因此,即使底层类型不是Copy
,x
也将始终是Copy
。示例:Playground
ct2axkht3#
你可以给每个闭包分别给予
&x
参数:Playground