4

我正在尝试了解 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);
    }
}

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

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

那我该怎么办?我理解为什么我不能存储对Appinside的引用Player,因为这会导致双重链接结构。但是我应该可以借用一个引用并对其执行操作,不是吗?

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

我通过selfreceive. 但是,如果我想app在 中可变receive怎么办?我不能self作为可变的传入,sender因为我也在借用player可变的。

4

2 回答 2

3

遵循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);
    }
}

最后一个资源是使用RefCell.

于 2016-04-29T14:03:26.727 回答
2

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

确实它已移至sender,但这不是此消息的内容。因为按值Player::receive取值self,您实际上必须分解app并移出player它才能调用receive. 在那个时间点,app现在是半成型的;它没有有效的价值player!如果receive试图访问app.player,它将使用无效内存。

“不能移出借来的内容” [...] 因为我们已经借用了self进入sender函数时的引用。

对,与上面有关。因为我们借用了App,所以我们不能player离开它,从而使 的App处于无效状态。

我应该能够借用参考并对其执行操作,不是吗?

你可以,只要你引用的东西在那个时候完全形成。上述说明中也有两个提示:

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

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

  2. 使App处于无效状态

    您可以使用类似的东西mem::replace放入不同 Playerapp. 然后它仍然完全(但不同)形成并且可以再次引用它。

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

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

是的!你会得到“不能*self一次多次借用可变”。但是,解决方案实际上基本相同!在调用方法之前将您分解App成更小的、不重叠的部分或分离playerself

于 2016-04-29T13:46:44.027 回答