【问题标题】:Edit RefCell in closure编辑 RefCell 关闭
【发布时间】:2021-06-27 21:05:02
【问题描述】:

我想在实现克隆的结构中存储一个闭包,所以我编写了这样的代码:

use std::rc::Rc;

type Closure = Box<dyn Fn() -> ()>;

#[derive(Clone)]
struct A {
    closure: Option<Rc<Closure>>,
}

impl A {
    pub fn new() -> A {
        A { closure: None }
    }

    pub fn closure(&self) -> Option<Rc<Closure>> {
        self.closure.clone()
    }

    pub fn set_closure(&mut self, closure: Closure) -> &mut Self {
        self.closure = Some(Rc::new(closure));
        self
    }
}

fn main() {
    let mut a: A = A::new();

    a.set_closure(Box::new(|| -> () { println!("Works fine!") }));
    (a.closure().unwrap())();
}

现在我想通过借用当前范围的变量来测试这段代码。在 main 函数中保留一个引用很重要,因为我需要在之后使用它。 我编码:

use std::cell::RefCell;

fn main() {
    let mut a: A = A::new();
    let value: Rc<RefCell<i8>> = Rc::new(RefCell::new(0));

    println!("Value = {}", value.borrow());

    a.set_closure(Box::new(|| -> () {
        *value.borrow_mut() = 1;
    }));
    (a.closure().unwrap())();

    println!("New value = {}", value.borrow());
}

但我收到此错误:

Compiling playground v0.0.1 (/playground)
error[E0597]: `value` does not live long enough
  --> src/main.rs:34:38
   |
34 |   a.set_closure(Box::new(|| -> () { *value.borrow_mut() = 1; }));
   |                 ---------------------^^^^^---------------------
   |                 |        |           |
   |                 |        |           borrowed value does not live long enough
   |                 |        value captured here
   |                 cast requires that `value` is borrowed for `'static`
...
38 | }
   | - `value` dropped here while still borrowed

请问有人知道我需要做什么吗? 感谢您提前回复。

【问题讨论】:

    标签: rust closures smart-pointers


    【解决方案1】:

    Rcs 通过克隆共享,这会增加它们的引用计数。但是您将对它的引用传递给闭包,这可能首先破坏了使用Rc 的意义。正如错误所说,在删除value 之后,闭包持有对value 的引用。

    你可能打算写这样的东西,它克隆Rc并将克隆移动到闭包中:

    let cloned_value = value.clone();
    a.set_closure(Box::new(move || *cloned_value.borrow_mut() = 1));
    

    或者(我的偏好)避免在外部范围中引入新的绑定:

    a.set_closure(Box::new({
        let value = value.clone();
        move || *value.borrow_mut() = 1
    }));
    

    【讨论】:

    • 感谢您的回复。我没想过要克隆Rc。我测试了它并且它有效。我还测试了您的第二个建议,但它不起作用。你知道为什么吗? Playground。对我来说这么多,我早上眯着眼睛阅读。它有效:D 谢谢你Playground OK
    猜你喜欢
    • 2014-03-24
    • 2011-08-01
    • 2010-09-05
    • 2013-10-26
    • 2010-09-17
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多