如何初始化包含引用的结构?

NSA*_*ict 3 initialization lifetime rust

我想为以下结构编写初始化器.

struct Foo {
    bar: &Bar
}
Run Code Online (Sandbox Code Playgroud)

它建议使用&TBox<T>的灵活性,这就是我要为这里.如果没有初始化器,您可以使用这样的结构.

{
    let bar = ...;
    let foo = Foo { bar: bar };

    // use foo    

    // dealloc bar and foo
}
Run Code Online (Sandbox Code Playgroud)

这有效.但我想&Bar在初始化器中分配.现在显然bar在堆栈上分配将无法工作,因为一旦初始化器返回它就超出了范围.所以我想我可以用Box.

fn new() -> Foo {
    let bar = Box::new(...);
    Foo { bar: &*bar }
}
Run Code Online (Sandbox Code Playgroud)

这也不起作用,因为我猜我们只是借用价值而不是转移所有权,bar一旦new返回仍然会解除分配.

Box在这种情况下,我是否被迫在结构中使用a ?

编辑

注意:需要引用的原因是因为Bar在我的情况下实际上是一个通用特征,因此大小可能会有所不同,这意味着堆栈上的分配将不起作用.

She*_*ter 7

你的问题没有意义.如果要在new方法中构造对象,那么根据定义,您知道类型是什么(因为您正在调用该构造函数),并且您不需要将其视为特征对象.你应该只使用这种类型!

需要引用的原因是因为Bar在我的情况下实际上是一个通用特征,因此大小可以变化,这意味着堆栈上的分配将不起作用.

这不完全正确!如果您想接受参数,并且想要转移所有权,那么您可以简单地将类型限制为您想要的特征:

trait Talker { fn talk(&self); }

struct Dog;
impl Talker for Dog { fn talk(&self) { println!("Woof") }}

struct Cat;
impl Talker for Cat { fn talk(&self) { println!("Meow") }}

struct OwnAGeneric<T: Talker> {
    t: T
}

impl<T: Talker> OwnAGeneric<T> {
    fn new(t: T) -> OwnAGeneric<T> { OwnAGeneric { t: t } }

    fn talk(&self) { println!("I own this:"); self.t.talk(); }
}

fn main() {
    let owned_cat = OwnAGeneric::new(Cat);  
    owned_cat.talk();
}
Run Code Online (Sandbox Code Playgroud)

这应该由编译器单一化,并且基本上与您手动编写代码一样快.这也允许在堆栈上分配所有内容.