如何将拥有的盒装结构引用给其他拥有的结构

时间:2016-03-14 10:08:51

标签: rust lifetime

suppressMessages(library(Zelig))拥有Engine,我希望WorkerEngine提供一些API作为特征的引用。 API实现使用Worker进行分配,并由Box拥有,因此只要worker工作,对它的引用就是稳定且有效的。

但我不明白如何在Rust中表达它。

我已阅读Why can't I store a value and a reference to that value in the same struct?,我理解为何我无法通过对自有价值的引用。但是,在我的情况下,我将引用传递给不是拥有值本身,而是传递给不会被移动的盒装值,因此对它的引用必须是稳定的。

这是非工作原型:

Engine

错误:

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

1 个答案:

答案 0 :(得分:2)

问题在于,在你的例子中,api对象没有任何东西可以比它创建的范围更长寿。所以基本上你需要创建整个引擎对象首先,然后Rust可以推断这些生命周期。但是你无法在不填写所有字段的情况下安全地创建对象。但您可以将worker字段更改为Option并稍后填写:

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

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

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