学习了一段时间的Rust,我开始以为我理解了它的所有权/借用机制,但是接下来的例子让我真的很疑惑。我在玩 rust-sdl2 :
extern crate sdl2;
use sdl2::Sdl;
use sdl2::event::Event;
use sdl2::render::Renderer;
struct SdlDriver<'a> {
sdl_ctx : Sdl,
renderer : Renderer<'a>
}
impl<'a> SdlDriver<'a> {
fn event_pump(&self) -> sdl2::event::EventPump {
self.sdl_ctx.event_pump()
}
fn draw_rect(&mut self, x: i32, y: i32) {
let mut drawer = self.renderer.drawer();
drawer.draw_rect(sdl2::rect::Rect::new(x-20, y-20, 40, 40));
drawer.present();
}
fn event_loop(&mut self) {
let mut event_pump = self.event_pump();
loop {
let event = event_pump.wait_event();
match event {
Event::Quit {..} => { break },
Event::MouseMotion { x, y, .. } => {
self.draw_rect(x, y);
},
_ => ()
}
}
}
}
fn main() {
}
编译器显示错误:
main.rs:32:25: 32:29 error: cannot borrow `*self` as mutable because it is also borrowed as immutable
main.rs:32 self.draw_rect(x, y);
^~~~
main.rs:24:34: 24:38 note: previous borrow of `*self` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `*self` until the borrow ends
main.rs:24 let mut event_pump = self.event_pump();
^~~~
main.rs:37:10: 37:10 note: previous borrow ends here
main.rs:23 fn event_loop(&mut self) {
...
main.rs:37 }
^
据我了解,对self.event_pump()
的调用应该暂时借用*self
,返回现在拥有的EventPump
结构通过event_loop()
,然后释放*self
。但看起来 *self
在 event_pump
的整个生命周期中都是借用的。为什么?
为了比较,当我调用方法而不返回结果时,比如
self.draw_rect(x, y);
self.draw_rect(x, y);
一切正常,*self
在每次调用后立即释放。
还有一个我不明白的是为什么*self
是借来的(带星号)? event_loop(&mut self)
已经从它的调用者那里借用了self
,为什么还要在这里借用*self
?
应该如何重写上面的示例以满足 Rust 的借用检查器?
最佳答案
the call to
self.event_pump
should temporarily borrow*self
是的
then return
EventPump
struct which is now owned byevent_loop
and release*self
没有。这是你的方法:
fn event_pump(&self) -> sdl2::event::EventPump {
self.sdl_ctx.event_pump()
}
在生命周期省略之前,它看起来像:
fn event_pump<'a>(&'a self) -> sdl2::event::EventPump<'a> {
self.sdl_ctx.event_pump()
}
EventPump
结构 looks like :
pub struct EventPump<'sdl> {
_sdl: PhantomData<&'sdl ()>,
// Prevents the event pump from moving to other threads.
// SDL events can only be pumped on the main thread.
_nosend: PhantomData<*mut ()>
}
当你借用self.sdl_ctx
时,你也在借用self
。借用检查器在 函数内进行细粒度检查,但不会跨 函数调用。即使在技术上可行,跨调用检查也会非常昂贵。
解决此问题的一种方法是直接调用成员变量上的方法 - 而不是创建您自己的 event_pump
方法,只需将其内联即可。这通常会导致创建更细粒度的结构。
关于rust - "the immutable borrow prevents mutable borrows"当使用 rust-sdl2 抽取事件时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29987374/