如何避免显式克隆移至闭包的变量?

问题描述 投票:0回答:1

有没有办法避免创建临时变量(在多个闭包中捕获变量):

  • 闭包中的
    move
    关键字是必需的
  • 只要将内部值传递给闭包,使用任何其他容器代替 Rc 就可以了
  • 克隆容器很好,我尝试了
    Copy
    特征,但不起作用,因为内部值是
    struct
use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug)]
struct MyStruct { value: u32 }

fn main() {
    
    let shared = Rc::new(RefCell::new(MyStruct { value: 42}));
    let shared_clone_1 = shared.clone();    // clone 1
    let shared_clone_2 = shared.clone();   // clone 2
    let shared_clone_3 = shared.clone();   // clone 3
    let shared_clone_4 = shared.clone();   // clone 4: can these clones be hidden?

    let closure_1 = move || { println!("closure_1 {:?}", shared); };
    let closure_2 = move || { println!("closure_2 {:?}", shared_clone_1); };
    let closure_3 = move || { println!("closure_3 {:?}", shared_clone_2); };
    let closure_4 = move || { println!("closure_4 {:?}", shared_clone_3); };
    let closure_5 = move || { println!("closure_5 {:?}", shared_clone_4); };
    
    closure_1();
    closure_2();
    closure_3();
    closure_4();
    closure_5();
}
rust closures borrow-checker ownership refcell
1个回答
0
投票

有没有办法避免创建临时变量(在多个闭包中捕获变量):

不是吗?如果您想执行“精确”的闭包捕获,那么您需要定义它们。尽管常见的方案是所谓的精确闭包模式,您可以在闭包本身周围执行闭包绑定,并隐藏外部变量:

let value = Rc::new(RefCell::new(MyStruct { value: 42}));

let closure_1 = {
    let value = value.clone();
    move || { println!("closure_1 {:?}", value); }
};
let closure_2 = {
    let value = value.clone();
    move || { println!("closure_2 {:?}", value); }
};

closure_1();
closure_2();

这使得捕获策略更容易查看。

闭包中的

move
关键字是必需的

move
闭包实际上只是意味着捕获的名称通过值传递,而默认情况下编译器将尝试使用限制最少的方案(在共享引用、唯一引用和复制/移动之间)。

因此,您可以在闭包外部创建引用并将引用移动到闭包中:

let value = MyStruct { value: 42};
let closure_1 = {
    let value = &value;
    move || { println!("closure_1 {:?}", value); }
};
let closure_2 = {
    let value = &value;
    move || { println!("closure_2 {:?}", value); }
};

closure_1();
closure_2();

克隆容器很好,我尝试了 Copy 特征,但不起作用,因为内部值是一个结构

不清楚你的意思,你需要

derive(Copy, Clone)
在你的结构上,尽管它要求that包含的所有内容都是它本身
Copy

#[derive(Copy, Clone, Debug)]
struct MyStruct { value: u32 }

fn main() {
    let value = MyStruct { value: 42};

    let closure_1 = move || { println!("closure_1 {:?}", value); };
    let closure_2 = move || { println!("closure_2 {:?}", value); };
    
    closure_1();
    closure_2();
}
© www.soinside.com 2019 - 2024. All rights reserved.