Pointers 将实现特征的数据存储在向量中

Pointers 将实现特征的数据存储在向量中,pointers,vector,rust,traits,lifetime,Pointers,Vector,Rust,Traits,Lifetime,一般来说,我对Rust和系统语言非常陌生。我现在正在和Rust一起探索语言。我有一个我自己无法解决的问题。我想我已经明白了问题所在 我不想将实现trait BaseStuff的对象存储在向量中。对我来说,这不是一项简单的任务:-) 下面是我的示例代码,它不会编译 trait BaseStuff {} struct MyStuff { value: i32, } struct AwesomeStuff { value: f32, text: String, } imp

一般来说,我对Rust和系统语言非常陌生。我现在正在和Rust一起探索语言。我有一个我自己无法解决的问题。我想我已经明白了问题所在

我不想将实现
trait BaseStuff
的对象存储在向量中。对我来说,这不是一项简单的任务:-)

下面是我的示例代码,它不会编译

trait BaseStuff {}

struct MyStuff {
    value: i32,
}

struct AwesomeStuff {
    value: f32,
    text: String,
}

impl BaseStuff for MyStuff {}

impl BaseStuff for AwesomeStuff {}

struct Holder {
    stuff: Vec<BaseStuff>,
}

impl Holder {
    fn register(&mut self, data: impl BaseStuff) {
        self.stuff.push(data);
    }
}

fn main() {
    let my_stuff = MyStuff { value: 100 };

    let awesome_stuff = AwesomeStuff {
        value: 100.0,
        text: String::from("I'm so awesome!"),
    };

    let mut holder = Holder { stuff: vec![] };

    holder.register(my_stuff);
}
现在我遇到了一个新的编译器问题:

错误[E0310]:参数类型
impl BaseStuff
可能无法长期使用 足够-->src\main.rs:22:25 | 21 | fn寄存器(&mut self), 数据:impl BaseStuff){|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |^^^^^^^^^^^^^^^^^^注:…以便 类型
impl BaseStuff
将满足其所需的生存期限制--> src\main.rs:22:25 | 22 | self.stuff.push(Box::new(data));
|^^^^^^^^^^^^^^

错误:由于上一个错误而中止

有关此错误的详细信息,请尝试
rustc--explain E0310
。 错误:无法编译

我知道我出局了……我在书中读到了关于生命的内容,并在这里用
'a
'a
以任何组合更改了我的代码,但没有运气……我不想写下我尝试过的任何生命定义组合。 我不明白为什么我需要生命周期定义。所有权在任何步骤中都会被移动,因此我很清楚Holder struct是所有数据的所有者。是吗

如何更正代码以进行编译

谢谢您的帮助。

您几乎可以得到它-这里的问题是
BaseStuff
实现的类型可能是一个引用(例如
impl BaseStuff for&SomeType
)。这意味着,即使您按值传递
数据,该值也可能是一个在
框中过期的引用

解决这一问题的方法是添加一个约束,使对象具有一个
静态
生存期,这意味着它将是一个值类型或静态引用。根据您的用例,您可以将此约束应用于trait或接受trait的方法

将约束应用于特征:

trait-BaseStuff:'static{}
将约束应用于方法:

impl支架{
fn寄存器(&mut self,数据:impl BaseStuff+'静态){
self.stuff.push(Box::new(data));
}
}
如果将
静态
约束添加到方法中,我建议也将其添加到
Vec
中,以避免丢失类型信息,如下所示:

struct Holder{

stuff:vec简单地说,这也会起作用:
data:impl-BaseStuff+'static
。但问题是为什么vec.push需要静态生存期。
data
必须已经移动了?ÖmerErden静态生存期是必需的,因为添加到向量中的数据本身可能是一个引用。
BaseStuff
可以为任何类型-例如,
impl BaseStuff for&SomeType
将允许您将类似于
&SomeType
的引用传递给该方法。这将触发生存期检查,因为引用本身存储在框中,而不是引用引用的值。哦,我应该先检查解释,谢谢。但我会请参阅将装箱数据发送到holder,但如果我将某一类型的引用装箱,然后将其发送到push,会发生什么情况?@ÖmerErden您能给我一个示例说明您的意思吗?装箱引用(
Box
)这似乎是一个奇怪的用例,但如果引用有一个
“静态”
生存期,它应该可以工作,否则就会失败。如果没有静态生存期,您可以通过只使用装箱的BaseStuff来解决此问题:
fn register(&mut self,data:Box)
,请检查。
struct Holder {
    stuff: Vec<Box<BaseStuff>>,
}

impl Holder {
    fn register(&mut self, data: impl BaseStuff) {
        self.stuff.push(Box::new(data));
    }
}