将自引用传递给包含对象的函数

Duk*_*Cat 5 reference rust borrowing

我正在尝试理解 Rust 的所有权模型。我试图在结构体上调用函数时传递对包含对象的引用。

这是我的结构:

pub struct Player {}

impl Player {
    pub fn receive(self, app: &App) {

    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码给了我“使用部分移动的值:self”。这是有道理的,因为App具有移动语义,因此该值sender在调用函数时被移动到函数中。

如果我更改它以便sender需要引用self,我会得到“无法移出借用的内容”,这也是有道理的,因为我们self在进入sender函数时借用了引用。

那我该怎么办?App我明白为什么我不能存储对inside 的引用Player,因为这会导致双向链接结构。但我应该能够借用一个引用并对其执行操作,不是吗?

我在官方教程中没有找到答案。

我通过self作为参考传递来解决它receive。但是如果我想app在 中可变怎么办receive?我不能以self可变的方式传递,sender因为我也player以可变的方式借用。

mal*_*rbo 7

遵循Shepmaster 解决方案的一种方法

在调用该方法之前取消关联playerself

是将其player放入Option

impl App {
    pub fn sender(&mut self) {
        let mut player = self.player.take();
        player.receive(&mut self);
        self.player = Some(player);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后一项资源是使用RefCell.


She*_*ter 2

因为具有移动语义,所以在调用函数时App该值被移动到函数中。sender

确实它已被移入sender,但这不是此消息的目的。因为按值Player::receive获取self,所以您实际上必须分解app并移出player它才能调用receive. 那时,app现在已半成形;它没有有效值player!如果receive尝试访问app.player,它将使用无效内存。

“无法移出借用的内容”[...] 因为我们借用了self进入该sender函数时的引用。

是的,这与上面相关。因为我们借用了 an App,所以我们无法移出player它,从而使App处于无效状态。

我应该能够借用一个引用并对其执行操作,不是吗?

你可以,只要你所引用的东西在那时已经完全形成了。上面的阐述中还有两个提示:

  1. 如果receive尝试访问app.player

    如果您不访问app.playerin receive,请重构代码以传递 的其他组件App而不是整个容器。也许你有一些GameState真正想要传递的东西。

  2. 使 处于App无效状态

    您可以使用类似的方法将不同的内容mem::replace放入. 然后它仍然是完全(但不同)形成的,并且可以再次引用它。 Playerapp

当然,更实际的解决方案是改为接受引用( &self)。

但是如果我想app在 中可变怎么办receive

是的!你会得到“不能*self一次借用多次”。然而,解决方案实际上基本相同!在调用该方法之前将其分解为App更小的、不重叠的部分或解除关联。playerself