将自引用传递给包含对象的函数 [英] Pass self reference to contained object's function

查看:20
本文介绍了将自引用传递给包含对象的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是我的结构:

pub struct Player {}impl 播放器 {pub fn 接收(自我,应用程序:&应用程序){}}

如您所见,receive 需要对 App 对象的引用.

pub struct App {酒吧播放器:播放器,}实现应用{pub fn 发件人(自己){//如何调用 player.test() 并将 self 作为引用传递?self.player.receive(&self);}}

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

如果我更改它以便 sender 引用对 self 的引用,我会得到无法移出借来的内容",这也有点道理,因为我们当我们进入 sender 函数时,已经借用了对 self 的引用.

那我该怎么办?我明白为什么我不能在 Player 中存储对 App 的引用,因为这会导致双向链接结构.但是我应该可以借用引用并对其进行操作,不是吗?

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

我通过在 receive 中传递 self 作为引用来解决它.但是如果我希望 appreceive 中是可变的怎么办?我不能在 sender 中将 self 作为可变传递,因为我也借用 player 作为可变.

解决方案

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

确实它被移到了 sender 中,但这不是这条消息的内容.因为 Player::receive 按值获取 self,你实际上必须分解 app 并将 player 移出它能够调用receive.在那个时间点,app 现在已经形成了一半;它对 player 没有有效值!如果 receive 尝试访问 app.player,它将使用无效内存.

<块引用>

不能搬出借来的内容"[...] 因为我们在进入 sender 函数时借用了对 self 的引用.

对,与上面有关.因为我们借用了一个App,我们不能将player移出它,从而使App处于无效状态.

<块引用>

我应该可以借用引用并对其进行操作,不是吗?

而且你可以,只要你所引用的东西在那个时候完全形成.上面的论述中也有两个提示:

  1. <块引用>

    如果 receive 尝试访问 app.player

    如果您没有在receive中访问app.player,请重构您的代码以传递App的其他组件而不是整个容器.也许您有一些 GameState 正是您想要传递的内容.

  2. <块引用>

    App 处于无效状态

    你可以使用类似mem::replace不同的 Player 放入app.然后它仍然完全(但不同)形成并且可以再次引用它.

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

<块引用>

但是如果我希望 appreceive 中是可变的怎么办?

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

I'm trying to grok Rust's ownership model. I'm trying to pass a reference to a containing object when calling a function on a struct.

Here's my struct:

pub struct Player {}

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

    }
}

As you can see, receive expects a reference to an App object.

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

The above code gives me "use of partially moved value: self". Which makes sense, because App has move semantics so the value was moved into the sender function when it was called.

If I change it so that sender takes a reference to self instead, I get "cannot move out of borrowed content", which also sort of makes sense because we've borrowed the reference to self when we went into the sender function.

So what do I do? I understand why I can't store a reference to App inside Player, since that would lead to a doubly-linked structure. But I should be able to borrow a reference and perform operations on it, no?

I couldn't find an answer in the official tutorial.

I solved it by passing self as a reference in receive. But what if I want app to be mutable in receive? I can't pass self as mutable in sender because I'm also borrowing player as mutable.

解决方案

because App has move semantics so the value was moved into the sender function when it was called.

It's true that it was moved into sender, but that's not what this message is about. Because Player::receive takes self by value, you actually had to decompose app and move player out of it to be able to call receive. At that point in time, app is now half-formed; it has no valid value for player! If receive tried to access app.player, it would be using invalid memory.

"cannot move out of borrowed content" [...] because we've borrowed the reference to self when we went into the sender function.

Right, which ties into above. Because we are borrowing an App, we cannot move player out of it, leaving the App in a invalid state.

I should be able to borrow a reference and perform operations on it, no?

And you can, so long as the thing you are taking a reference to is completely formed at that point. There were also two hints in the above exposition:

  1. If receive tried to access app.player

    If you don't access app.player in receive, restructure your code to pass the other components of App instead of the entire container. Maybe you have some GameState that is really what you want to pass.

  2. leaving the App in a invalid state

    You can use something like mem::replace to put in a different Player into app. Then it's still completely (but differently) formed and can have a reference to it taken again.

Of course, the more practical solution is to change to accept references (&self).

But what if I want app to be mutable in receive?

Yup! You'd get "cannot borrow *self as mutable more than once at a time". The solutions are actually basically the same, however! Decompose your App into smaller, non-overlapping pieces or disassociate player from self before calling the method.

这篇关于将自引用传递给包含对象的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆