获取 move closure 的引用报错,请指正问题所在

有下面的代码

1.  fn boxed_closure(closures: &mut Vec<&dyn Fn()>) {
2.      let v = "abc".to_string();
3.      let v = 1; 
4.      closures.push(&||println!("first"));
5.      closures.push(&|| println!("second"));
6.      closures.push(&move || println!("v's value:{}",v));
7.  }
8.
9.  fn main() {
10.    let mut closures:Vec<&dyn Fn()> = vec![];
11.
12.    boxed_closure(&mut closures);
13. }

在函数 boxed_closure 中,第 4 行和第 5 行都没有报错,但是第6行报错:

1 | fn boxed_closure(closures: &mut Vec<&dyn Fn()>) {
  |                                     - let's call the lifetime of this reference `'1`
...
6 |     closures.push(&move || println!("v's value:{}",v));
  |     ---------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
  |     |              |
  |     |              creates a temporary value which is freed while still in use
  |     argument requires that borrow lasts for `'1`

看了rust 的 temporary lifetime extentsion 的相关文档没有找到问题的原因,因为文档中就没有提到 move closure 相关的临时对象。

我猜测报错的原因是,move closure 虽然把 v 的所有权转移到 closure 中,但是rust仍然认为 closure 使用的是函数 boxed_closure 中局部变量 v 的 &v,所以导致编译失败。

请哪位大牛解答一下,谢谢!

讨论数量: 9
长日将尽

报错说明的是你持有了一个临时值的引用。closures.push(&move || println!("v's value:{}",v)); 中你创建一个临时的闭包,然后把这个闭包的引用存入 Vec 中,但是语句这个闭包在语句结束后就会被释放,导致 Vec 中存入的引用指向一个无效的内存。

1周前 评论
dewei (楼主) 1周前
长日将尽 (作者) 1周前

@长日将尽 这位大佬其实已经告诉你为什么了,可以参考我的刚刚记录的一个笔记。 @dewei

www.yuque.com/anruofusheng/bytlpr/...

这里传递过去的还是临时值,rust是不允许这种操作的,你这个还是想着引用传递的那一套,除非你搞一些骚操作。你要么clone一下,要么就使用指针。

1周前 评论
长日将尽 1周前
dewei (楼主) 1周前
fn boxed_closure(closures: &mut Vec<Box<dyn Fn()>>) {
    let v = 1;
    closures.push(Box::new(move || println!("first")));
    closures.push(Box::new(move || println!("second")));
    let f = Box::new(move || println!("v's value:{}", v));
    closures.push(f);
}

fn main() {
    let mut closures: Vec<Box<dyn Fn()>> = vec![];
    boxed_closure(&mut closures);
}

没有不认真看你的代码,已经说的很清楚了。move只是修改所有权,又不是提升生命周期的。

给你完整可以运行的代码吧,你可以自己查一个Box是干什么的@dewei

1周前 评论
dewei (楼主) 4天前

对计算机内存管理、堆栈管理没有什么概念的话,建议还是听编译器的提示修改。楼主让我想起来之前给某些大公司做技术支持时,有个老哥使用定时器判断http请求是否超时,然后还觉得自己搞的很对,不理解这样为什么不行。把我怼了半天。

3天前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!