处理由不同结构借用的多个可变引用

时间:2017-09-19 07:09:49

标签: rust undefined-behavior mutable lifetime borrow-checker

我对Rust比较陌生,想通过与活塞建立游戏来学习它。

我有一个Renderer结构渲染场景和一个处理游戏逻辑事件的主循环。他们都需要一个可变的借用,我理解多次借用可能会导致未定义的行为,但我不明白它在我的情况下是怎么做的,因为我总是在不同的范围和<中使用该对象strong>相同的帖子。

我查看了this问题,觉得我应该使用Rc和/或RefCell来解决这个问题,但这似乎太极端了。我也不认为我需要渲染器中的所有权(或者是我,那么为什么?),因为渲染器的寿命比主循环短。

另一个解决方案是每次需要时传递可变对象,但在实际情况下,这几乎适用于所有函数,而且我来自Java / C ++,下面的代码可以工作。

struct Renderer<'a> {
    w: &'a mut Window,
}

impl<'a> Renderer<'a> {
    fn render(&mut self) {
        let w = &mut self.w;
        // complex render operation needing the window mutably
    }
}

struct Window {
    //...
}

impl Window {
    fn poll_event(&mut self) {
        //some internal code of piston
    }
}

fn main() {
    let mut w = Window {};
    let mut renderer = Renderer { w: &mut w };

    loop {
        {
            //first event handling
            w.poll_event();
        }
        {
            //AFTERWARDS rendering
            renderer.render();
        }
    }
}

错误:

error[E0499]: cannot borrow `w` as mutable more than once at a time
  --> src/main.rs:29:13
   |
24 |     let mut renderer = Renderer { w: &mut w };
   |                                           - first mutable borrow occurs here
...
29 |             w.poll_event();
   |             ^ second mutable borrow occurs here
...
36 | }
   | - first borrow ends here

我的Rc方法编译得很好,但似乎超出了顶部:

use std::rc::Rc;

struct Renderer {
    w: Rc<Window>,
}

impl Renderer {
    fn render(&mut self) {
        let w = Rc::get_mut(&mut self.w).unwrap();
        // complex render operation needing the window mutably
    }
}

struct Window {
    //...
}

impl Window {
    fn poll_event(&mut self) {
        //some internal code of piston
    }
}

fn main() {
    let mut w = Rc::new(Window {});
    let mut renderer = Renderer { w: w.clone() };

    loop {
        {
            //first event handling
            Rc::get_mut(&mut w).unwrap().poll_event();
        }
        {
            //AFTERWARDS rendering
            renderer.render();
        }
    }
}

我实际需要做的就是延迟&mut。这适用于Rc,但我不需要所有权 - 因此所有unwrap内容都不会失败,因为我(可以)在不同的范围内使用它。

这种困境可以解决,还是我在这种情况下被迫使用Rc

如果有更“生锈”的方式,请告诉我。

0 个答案:

没有答案