将自引用传递给包含对象的函数
Pass self reference to contained object's function
我正在尝试理解 Rust 的所有权模型。在结构上调用函数时,我试图传递对包含对象的引用。
这是我的结构:
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);
}
}
上面的代码给了我"use of partially moved value: self
"。这是有道理的,因为 App
具有移动语义,所以该值在被调用时被移动到 sender
函数中。
如果我更改它以便 sender
引用 self
,我得到 "cannot move out of borrowed content",这也有点道理,因为我们借用了 self
的引用=14=] 当我们进入 sender
函数时。
那我该怎么办?我明白为什么我不能在 Player
中存储对 App
的引用,因为那样会导致双向链接结构。但是我应该可以借用一个引用并对其进行操作,不是吗?
在官方教程中找不到答案
我通过在receive
中传递self
作为参考来解决它。但是,如果我希望 app
在 receive
中可变怎么办?我不能在 sender
中将 self
作为可变传递,因为我还借用了 player
作为可变。
because App
has move semantics so the value was moved into the sender
function when it was called.
它确实已移至 sender
,但这不是此消息的内容。因为 Player::receive
按值获取 self
,实际上您必须分解 app
并将 player
移出它才能调用 receive
。在那个时间点,app
现在已经半成型了;它没有 player
的有效值!如果 receive
尝试访问 app.player
,它将使用无效内存。
"cannot move out of borrowed content" [...] because we've borrowed the reference to self
when we went into the sender
function.
对,这与上面有关。因为我们借用了一个 App
,所以我们不能将 player
移出它,使 App
处于无效状态。
I should be able to borrow a reference and perform operations on it, no?
你可以,只要你参考的东西在那个时候已经完全形成。上面的说明中还有两个提示:
-
If receive
tried to access app.player
如果您不访问 receive
中的 app.player
,请重构您的代码以传递 App
的其他组件而不是整个容器。也许你有一些GameState
是你真正想要传递的。
-
leaving the App
in a invalid state
您可以使用 mem::replace
之类的东西将 不同的 Player
放入 app
。然后它仍然完全(但不同)形成并且可以再次引用它。
当然,更实际的解决办法是改成accept references(&self
)。
But what if I want app
to be mutable in receive
?
是啊!你会得到“不能一次多次借用 *self
作为可变”。然而,解决方案实际上基本相同!在调用方法之前,将 App
分解成更小的、不重叠的片段或从 self
中分离 player
。
一种遵循方式
disassociate player
from self
before calling the method.
就是把player
放在一个Option
中:
impl App {
pub fn sender(&mut self) {
let mut player = self.player.take();
player.receive(&mut self);
self.player = Some(player);
}
}
最后一个资源是使用 RefCell
。
我正在尝试理解 Rust 的所有权模型。在结构上调用函数时,我试图传递对包含对象的引用。
这是我的结构:
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);
}
}
上面的代码给了我"use of partially moved value: self
"。这是有道理的,因为 App
具有移动语义,所以该值在被调用时被移动到 sender
函数中。
如果我更改它以便 sender
引用 self
,我得到 "cannot move out of borrowed content",这也有点道理,因为我们借用了 self
的引用=14=] 当我们进入 sender
函数时。
那我该怎么办?我明白为什么我不能在 Player
中存储对 App
的引用,因为那样会导致双向链接结构。但是我应该可以借用一个引用并对其进行操作,不是吗?
在官方教程中找不到答案
我通过在receive
中传递self
作为参考来解决它。但是,如果我希望 app
在 receive
中可变怎么办?我不能在 sender
中将 self
作为可变传递,因为我还借用了 player
作为可变。
because
App
has move semantics so the value was moved into thesender
function when it was called.
它确实已移至 sender
,但这不是此消息的内容。因为 Player::receive
按值获取 self
,实际上您必须分解 app
并将 player
移出它才能调用 receive
。在那个时间点,app
现在已经半成型了;它没有 player
的有效值!如果 receive
尝试访问 app.player
,它将使用无效内存。
"cannot move out of borrowed content" [...] because we've borrowed the reference to
self
when we went into thesender
function.
对,这与上面有关。因为我们借用了一个 App
,所以我们不能将 player
移出它,使 App
处于无效状态。
I should be able to borrow a reference and perform operations on it, no?
你可以,只要你参考的东西在那个时候已经完全形成。上面的说明中还有两个提示:
-
If
receive
tried to accessapp.player
如果您不访问
receive
中的app.player
,请重构您的代码以传递App
的其他组件而不是整个容器。也许你有一些GameState
是你真正想要传递的。 -
leaving the
App
in a invalid state您可以使用
mem::replace
之类的东西将 不同的Player
放入app
。然后它仍然完全(但不同)形成并且可以再次引用它。
当然,更实际的解决办法是改成accept references(&self
)。
But what if I want
app
to be mutable inreceive
?
是啊!你会得到“不能一次多次借用 *self
作为可变”。然而,解决方案实际上基本相同!在调用方法之前,将 App
分解成更小的、不重叠的片段或从 self
中分离 player
。
一种遵循方式
disassociate
player
fromself
before calling the method.
就是把player
放在一个Option
中:
impl App {
pub fn sender(&mut self) {
let mut player = self.player.take();
player.receive(&mut self);
self.player = Some(player);
}
}
最后一个资源是使用 RefCell
。