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

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

问题描述

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



这是我的结构:

  pub struct Player {} 

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

}
}

如您所见,接收期望引用 App 对象。

  pub struct App {
pub player:Player,
}

impl App {
pub fn sender(self){
//如何调用player.test()并将self作为参考传递?
self.player.receive(& self);
}
}

上面的代码给我使用部分变动的价值:自我。这是有道理的,因为 App 具有移动语义,因此在调用该值时将其值移到了 sender 函数中。 / p>

如果我进行更改,以使发件人引用自己相反,我得到无法移出借用的内容,这也很有意义,因为当我们进入<$时,我们借用了 self 的引用。 c $ c> sender 函数。



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



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



我通过在 receive 中传递 self 作为参考来解决它。但是,如果我希望 app receive 中可变吗?我不能通过 self sender 中可变,因为我也借了 player 可变。

解决方案


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


确实已将其移至发件人中,但这不是此消息的含义。由于 Player :: receive 的价值在于本身,因此您实际上必须分解 app 并将播放器从其中移出,以便能够呼叫接收。那时, app 的格式已经变成一半了;对于播放器没有有效值!如果接收尝试访问 app.player ,则它将使用无效的内存。


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


右图,与上面的内容相关。因为我们要借用 App ,所以不能将 player 移出它,而留下 App 处于无效状态。


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


您可以,只要您要引用的东西在那时完全形成即可。上面的博览会还有两个提示:



  1. 如果接收尝试访问 app.player


    如果您没有在接收中访问 app.player ,而是重构代码以传递<$ c $的其他组件c> App 而不是整个容器。也许您有一些真正想要传递的 GameState



  2. App 置于无效状态


    您可以使用类似 mem :: replace Player 放入 app 。然后它仍然是完整的(但形式不同),可以再次引用它。


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


但是,如果我希望 app receive 中是可变的,怎么办?


是的!您将得到一次不能多次借用 * self 。实际上,解决方案基本相同!将您的 App 分解成较小的,不重叠的片段,或将 player self ,然后再调用该方法。


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天全站免登陆