我的结构中有一个RefCell
,我想访问和修改它。但是,访问此RefCell
的唯一方法是使用闭包。因此,我想从闭包中返回一个mutable reference(RefMut
),我可以在封闭范围内使用和修改它。
{
let mut state_ref: RefMut<_> = self.dialog.call_on_name("dirview", |view: &mut Canvas<RefCell<FileDialogState>>| {
let state: &RefCell<FileDialogState> = view.state_mut();
state.borrow_mut()
}).unwrap();
state_ref.foo = bar;
// Mutable reference to RefCell should cease to exist here
}
但是,编译器提示我返回的RefMut
超过了我创建它的闭包的生存期。尽管如此,我仍然看到了一些代码,它们的功能与我想要实现的功能类似-例如here:
impl Backend {
pub fn init() -> ... {
let stdout = RefCell::new(BufWriter::new(io::stdout()));
...
}
fn stdout_mut(&self) -> RefMut<BufWriter<Stdout>> {
self.stdout.borrow_mut()
}
这两个用例之间有什么区别?我缺少什么才能返回RefMut
引用?
最佳答案
RefCell
动态检查共享的可变访问,但不能动态管理整个单元的所有权(这是Rc
之类的工作)。 Ref
或RefMut
仅在存在底层RefCell
的情况下才有效,这就是为什么您不能从此闭包返回RefMut
的原因:在该代码的结构中无法保证RefCell
会继续存在。 (如果.state_mut()
的类型为返回的引用指定了足够长的生存期,则可能存在,但是显然没有。)
在第二种情况下,stdout_mut
消除了生存期,该生存期将返回的RefMut
的生存期参数链接到&self
的生存期,从而提供了必要的保证。 (如果将 Lint 设置更改为#[warn(elided_lifetimes_in_paths)]
,则当用户定义类型的生命周期参数被删除时,您将收到一条警告,这可以使这一点更加清楚。)
要在第一种情况下解决您的问题,您可以:
Rc<RefCell<_>>
而不是RefCell<_>
。然后,您可以从闭包中返回Rc::clone(view.state_mut())
,然后再借用它。关于rust - 从闭包中返回时的RefMut生命周期错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65675881/