使用内部可变性模式的“BorrowMutError”
Posted
技术标签:
【中文标题】使用内部可变性模式的“BorrowMutError”【英文标题】:"BorrowMutError" using the Interior Mutability Pattern 【发布时间】:2020-12-30 23:44:29 【问题描述】:我正在尝试使用内部可变性模式来共享可变引用。
但是,当我尝试使用与它共享的结构中的引用时,程序会出现以下错误:
thread 'main' panicked at 'already borrowed: BorrowMutError'
代码如下:
use std::rc::Rc;
use std::cell::RefCell;
fn main()
let game = Game::init();
game.start();
struct Game
ecs: Rc<RefCell<Ecs>>,
impl Game
pub fn init() -> Game
let ecs = Rc::new(RefCell::new(Ecs::new()));
ecs.borrow_mut().register_systems(vec![
Box::new(Renderer
ecs: Rc::clone(&ecs),
),
]);
Game
ecs: Rc::clone(&ecs),
pub fn start(&self)
self.ecs.borrow_mut().update();
struct Ecs
systems: Vec<Box<dyn System>>,
impl Ecs
fn new() -> Ecs
Ecs
systems: vec![],
fn register_systems(&mut self, systems: Vec<Box<dyn System>>)
self.systems = systems;
fn update(&self)
for system in self.systems.iter()
system.update();
fn test(&self)
println!("done!");
trait System
fn update(&self);
struct Renderer
ecs: Rc<RefCell<Ecs>>,
impl System for Renderer
fn update(&self)
self.ecs.borrow_mut().test();
问题似乎出在这条线上:
self.ecs.borrow_mut().test();
这里有什么问题?跟性格有关系吗?还是我需要以其他方式调用函数test
?
【问题讨论】:
这条信息似乎完全正确:你borrow_mut()
两次使用相同的 RefCell
(通过两个不同的 Rc
指向它的指针),这正是你不能做的事情。
【参考方案1】:
确实,Renderer
中的 ecs
成员是 ecs
成员的克隆
在Game
,即他们都拥有相同的Ecs
。
当你 borrow_mut()
ecs
成员在 Game
然后迭代
元素,你到达Renderer
其中borrow_mut()
s
同样Ecs
。
这是在运行时检测到的,然后发生恐慌,这是预期的
RefCell
的行为。
如果您在这两种情况下都将borrow_mut()
更改为borrow()
,
这不再恐慌,因为多个不可变借用
是允许的。
我不知道这段代码的确切用途,但我不确定
从Renderer
借用Ecs
是个好主意。
我认为内部可变性应该适用于每个
单独存储组件而不是整个Ecs
。
【讨论】:
以上是关于使用内部可变性模式的“BorrowMutError”的主要内容,如果未能解决你的问题,请参考以下文章