Rust 如何将已拥有的盒式结构引用到其他已拥有的结构

Rust 如何将已拥有的盒式结构引用到其他已拥有的结构,rust,lifetime,Rust,Lifetime,我有Engine,它拥有Worker,我想Engine为Worker提供一些API,作为trait的参考。API实现是使用框分配的,属于引擎,因此只要工作人员还活着,对它的引用就稳定有效 但我不明白如何用锈来表达它 我已经阅读并理解为什么我不能传递对自有价值的引用。然而,在我的例子中,我传递的引用不是拥有的值本身,而是装箱的值,它不会被移动,所以对它的引用必须是稳定的 以下是非工作原型: trait EngineApi { fn foo(&self); } struct Wor

我有
Engine
,它拥有
Worker
,我想
Engine
Worker
提供一些API,作为trait的参考。API实现是使用
分配的,属于
引擎
,因此只要工作人员还活着,对它的引用就稳定有效

但我不明白如何用锈来表达它

我已经阅读并理解为什么我不能传递对自有价值的引用。然而,在我的例子中,我传递的引用不是拥有的值本身,而是装箱的值,它不会被移动,所以对它的引用必须是稳定的

以下是非工作原型:

trait EngineApi {
    fn foo(&self);
}

struct Worker<'a> {
    api: &'a EngineApi,
}
impl<'a> Worker<'a> {
    fn new(engine_api: &'a EngineApi) -> Self {
        Worker { api: engine_api }
    }
}

struct Api;
impl EngineApi for Api {
    fn foo(&self) {} 
}

struct Engine<'a> {
    api: Box<Api>,
    worker: Box<Worker<'a>>,
}

impl<'a> Engine<'a> {
    fn new() -> Self {
        let api = Box::new(Api);
        let worker = Box::new(Worker::new(api.as_ref()));
        Engine { api: api, worker: worker }
    }
}

fn main() {
    let engine = Engine::new();
}

问题在于,在您的示例中,没有任何东西会将
api
对象绑定到比其创建范围更长的时间。所以基本上你需要先创建整个引擎对象,然后生锈可能会导致这些生命周期。但是,如果不填写所有字段,就无法安全地创建对象。但您可以将
工作者
字段更改为
选项
,稍后再填写:

struct Engine<'a> {
    api: Box<Api>,
    worker: Option<Box<Worker<'a>>>,
}

impl<'a> Engine<'a> {
    fn new() -> Self {
        let api = Box::new(Api);
        Engine { api: api, worker: None }
    }
    fn turn_on(&'a mut self) {
        self.worker = Some(Box::new(Worker::new(self.api.as_ref())));
    }
}

fn main() {
    let mut engine = Engine::new();
    engine.turn_on();
}

Rust编译器不能使用对象应该是可移动的这一事实,因为它引用的东西存储在堆上,并且至少与对象一样长。也许将来某一天。现在,您必须求助于不安全的代码。

可能重复我读过的问题,我理解为什么我不能存储对所属值的引用-因为值在存储到结构时会移动,以后在结构本身移动时会移动。然而,在我的案例中,值是装箱的,所以引用是稳定的,虽然它可能无法用Rust表示,但它必须是有效的。在这种情况下,你能(1)在你的问题中引用这个链接,并(2)在你的问题中解释你理解的内容以及你认为你的案例不同的原因吗?这将帮助我们准确地理解该解释什么。这种自锁只是一种魔力。我花了一点时间才理解了开机前(我可以将发动机移动到任何地方)和开机后(发动机无法移动)之间的行为差异,但我仍然不确定我是否已经整理好了所有细节。事实上,之后它是不可移动的,这可能会让人痛苦(没有关闭的功能)。是的,这种自锁功能真的很酷。然而,我不喜欢两阶段初始化,所以我可能会求助于通过Rc共享API。
struct Engine<'a> {
    api: Box<Api>,
    worker: Option<Box<Worker<'a>>>,
}

impl<'a> Engine<'a> {
    fn new() -> Self {
        let api = Box::new(Api);
        Engine { api: api, worker: None }
    }
    fn turn_on(&'a mut self) {
        self.worker = Some(Box::new(Worker::new(self.api.as_ref())));
    }
}

fn main() {
    let mut engine = Engine::new();
    engine.turn_on();
}
struct Engine<'a> {
    api: Api,
    worker: Option<Worker<'a>>,
}

impl<'a> Engine<'a> {
    fn new() -> Self {
        let api = Api;
        Engine { api: api, worker: None }
    }
    fn turn_on(&'a mut self) {
        self.worker = Some(Worker::new(&self.api));
    }
}

fn main() {
    let mut engine = Engine::new();
    engine.turn_on();
}