我试图了解Rust的所有权模式。我在调用struct上的函数时尝试传递对包含对象的引用。
这是我的结构:
pub struct Player {}
impl Player {
pub fn receive(self, app: &App) {
}
}
如您所见,receive
需要引用App
对象。
pub struct App {
pub player: Player,
}
impl App {
pub fn sender(self) {
// how to call player.test() and pass self as a reference?
self.player.receive(&self);
}
}
以上代码为我提供了使用部分移动的值:self
"。这是有道理的,因为App
具有移动语义,所以当调用它时,值被移动到sender
函数中。
如果我更改它以便sender
引用self
,我会得到"无法移出借来的内容",这也是有道理的,因为我们&# 39;当我们进入self
函数时,我借用了对sender
的引用。
那我该怎么办?我理解为什么我无法在App
内存储Player
的引用,因为这会导致双重链接结构。但是我应该可以借用一个引用并对它进行操作,不是吗?
我在官方教程中找不到答案。
我通过在self
中传递receive
作为参考来解决它。但是,如果我希望app
中receive
可变,该怎么办?我无法在self
中将sender
作为可变对象,因为我还借用player
作为可变对象。
答案 0 :(得分:3)
在调用方法之前,将
player
与self
取消关联。
是将player
放入Option
:
impl App {
pub fn sender(&mut self) {
let mut player = self.player.take();
player.receive(&mut self);
self.player = Some(player);
}
}
最后一项资源是使用RefCell
。
答案 1 :(得分:2)
因为
App
具有移动语义,所以在调用它时,值被移动到sender
函数中。
确实已将其移至sender
,但这不是此消息的内容。由于Player::receive
按值self
获取,因此您实际上必须分解app
并将player
移出其中才能调用receive
。在那个时间点,app
现在是半成形的;它没有player
的有效值!如果receive
尝试访问app.player
,则会使用无效内存。
"无法摆脱借来的内容" [...]因为我们在进入
self
函数时借用了对sender
的引用。
对,这与上述联系在一起。由于我们正在借用App
,因此我们无法移动player
,导致App
处于无效状态。
我应该可以借用一个引用并对它执行操作,不是吗?
你可以,只要你参考的东西完全在那时形成。上述论述中还有两个提示:
如果
receive
试图访问app.player
如果您无法访问app.player
中的receive
,请重新构建代码以传递App
的其他组件,而不是整个容器。也许你有一些GameState
,这是你想要传递的。
将
App
置于无效状态
您可以使用mem::replace
之类的内容将不同的 Player
放入app
。然后它仍然完全(但不同)形成,并可以再次参考它。
当然,更实际的解决方案是更改为接受引用(&self
)。
但是,如果我希望
app
中的receive
可变,那该怎么办?
烨!你得到的#{1}不能一次性地多次使用*self
和#34;然而,解决方案实际上基本相同!在调用方法之前,将App
分解为较小的,不重叠的部分或将player
与self
取消关联。