提问人:user2925565 提问时间:3/22/2023 最后编辑:Stargateuruser2925565 更新时间:3/23/2023 访问量:93
即使标记了生存期,闭包的寿命也可能超过当前函数
Closure may outlive the current function even if the lifetime is marked
问:
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();
}
}
}
导致错误
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?x
我知道我可以在闭包上添加关键字来修复它。但是如果 x 不是 i64 而是非 Copy 结构,那么这个方法应该不起作用。move
另外,我认为我的代码中没有内存问题,如何说服 rust 编译器相信它?
答:
2赞
cafce25
3/22/2023
#1
问题在于,如果没有编译器的建议,本地引用就会被引用,并且只有该引用存储在闭包中。但确实在最后被释放了,所以参考现在悬而未决。要修复它,您可以简单地应用编译器的建议,在每个闭包前面添加。move
x
x
get_closures
move
移动不会复制引用后面的内容,而是复制引用本身,这正是您想要的。T
评论
0赞
Jonas Fassbender
3/22/2023
下面是一个不可复制类型的示例,说明您的描述
1赞
Jmb
3/22/2023
#2
注意它不是类型,而是类型,即引用 。即使基础类型不是,也始终如此。例:x
i64
&i64
i64
x
Copy
fn get_closeures<'a>(x: &'a str) -> Vec<Box<dyn Fn() + 'a>> {
let mut ret: Vec<Box<dyn Fn() -> ()>> = Vec::new();
ret.push(Box::new(move || println!("{}", x)));
ret.push(Box::new(move || println!("{}", x)));
ret
}
fn main() {
let x: String = "azerty".to_string();
{
let closures = get_closeures(&x);
for closure in closures {
closure();
}
}
}
0赞
Kaplan
3/23/2023
#3
您可以分别为每个闭包提供参数:&x
fn get_closures() -> Vec<fn(&i64)> {
let mut ret: Vec<fn(&i64)> = vec![];
ret.push(|x| println!("{}", x + 1));
ret.push(|x| println!("{}", x + 2));
ret
}
评论
&&i64
&i64