如何初始化包含引用的结构?
How do I initialise a struct that contains a reference?
我想为以下结构编写初始化程序。
struct Foo {
bar: &Bar
}
建议使用 &T
而不是 Box<T>
以获得灵活性,这就是我在这里的目的。如果没有初始化程序,您将使用这样的结构。
{
let bar = ...;
let foo = Foo { bar: bar };
// use foo
// dealloc bar and foo
}
这行得通。但是我想在初始化程序中分配 &Bar
。现在显然在堆栈上分配 bar
是行不通的,因为一旦初始化 returns 就超出了范围。所以我想我可以使用 Box
.
fn new() -> Foo {
let bar = Box::new(...);
Foo { bar: &*bar }
}
这也不起作用,因为我猜我们只是借用价值而不是转移所有权,这仍然会释放 bar
一次 new
returns。
在这种情况下,我是否被迫在结构中使用 Box
?
编辑
注意:需要引用的原因是因为 Bar
在我的例子中实际上是一个通用特征,因此大小可以变化,这意味着在堆栈上分配不行。
如果不知道 Bar
是什么,就很难确定。如果它是一个特征,那么是的,它需要是 &Bar
或 Box<Bar>
。如果只是常规类型,那么正常的做法是直接存储:
struct Foo {
bar: Bar
}
当您听说 &Bar
是灵活性的首选时,这通常与函数参数有关,例如fn func(bar: &Bar)
,即便如此,这实际上取决于您实际在做什么。但是,在结构上定义字段时,直接存储值通常是您想要的,除非您知道自己在做什么。这清楚地表明 Foo
拥有 Bar
.
你的问题没有道理。如果您在 new
方法中构造对象,那么根据定义 您知道类型是什么 (因为您正在调用该构造函数),并且您不需要将其视为特征对象。你应该只使用类型!
The reason the reference is needed is because Bar is actually a generic trait in my case and thus the size can vary which means allocation on the stack won't work.
这不完全正确!如果你想接受一个参数,并且你想转移所有权,那么你可以简单地将类型限制为你想要的特征:
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();
}
这应该由编译器单态化,并且基本上和您手动编写代码一样快。这也允许在堆栈上分配所有内容。
我想为以下结构编写初始化程序。
struct Foo {
bar: &Bar
}
建议使用 &T
而不是 Box<T>
以获得灵活性,这就是我在这里的目的。如果没有初始化程序,您将使用这样的结构。
{
let bar = ...;
let foo = Foo { bar: bar };
// use foo
// dealloc bar and foo
}
这行得通。但是我想在初始化程序中分配 &Bar
。现在显然在堆栈上分配 bar
是行不通的,因为一旦初始化 returns 就超出了范围。所以我想我可以使用 Box
.
fn new() -> Foo {
let bar = Box::new(...);
Foo { bar: &*bar }
}
这也不起作用,因为我猜我们只是借用价值而不是转移所有权,这仍然会释放 bar
一次 new
returns。
在这种情况下,我是否被迫在结构中使用 Box
?
编辑
注意:需要引用的原因是因为 Bar
在我的例子中实际上是一个通用特征,因此大小可以变化,这意味着在堆栈上分配不行。
如果不知道 Bar
是什么,就很难确定。如果它是一个特征,那么是的,它需要是 &Bar
或 Box<Bar>
。如果只是常规类型,那么正常的做法是直接存储:
struct Foo {
bar: Bar
}
当您听说 &Bar
是灵活性的首选时,这通常与函数参数有关,例如fn func(bar: &Bar)
,即便如此,这实际上取决于您实际在做什么。但是,在结构上定义字段时,直接存储值通常是您想要的,除非您知道自己在做什么。这清楚地表明 Foo
拥有 Bar
.
你的问题没有道理。如果您在 new
方法中构造对象,那么根据定义 您知道类型是什么 (因为您正在调用该构造函数),并且您不需要将其视为特征对象。你应该只使用类型!
The reason the reference is needed is because Bar is actually a generic trait in my case and thus the size can vary which means allocation on the stack won't work.
这不完全正确!如果你想接受一个参数,并且你想转移所有权,那么你可以简单地将类型限制为你想要的特征:
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();
}
这应该由编译器单态化,并且基本上和您手动编写代码一样快。这也允许在堆栈上分配所有内容。