Types 类型定义与特征:指定显式生存期界限的区别?

Types 类型定义与特征:指定显式生存期界限的区别?,types,rust,traits,Types,Rust,Traits,当我在类型定义中使用特征时,我在理解生命周期限制需求方面遇到了问题。例如: trait Kind { /* ... */ } type CollectionOfKind<'a> = Vec<&'a Kind>; // => error: explicit lifetime bound required trait-Kind{/*…*/} 类型收集fkind; //=>错误:需要显式的生存期界限 对于结构(,)中的特征,已经讨论了生命周期界限的要求。起初,

当我在类型定义中使用特征时,我在理解生命周期限制需求方面遇到了问题。例如:

trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a Kind>;
// => error: explicit lifetime bound required
trait-Kind{/*…*/}
类型收集fkind;
//=>错误:需要显式的生存期界限
对于结构(,)中的特征,已经讨论了生命周期界限的要求。起初,我在这里应用“添加生存期”的方法时遇到了问题,因为这不起作用:

type CollectionOfKind<'a> = Vec<&'a Kind + 'a>;
type CollectionOfKind<'a> = Vec<&'a Kind + 'static>;
类型CollectionOfKind=Vec;
然而,这只是一个语法问题,正如@Shepmaster所指出的那样

总的来说,我现在找到了三种指定生存期界限的方法:

// Version 1: Adding 'static to the trait itself
trait Kind : 'static { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a Kind>;
//版本1:将“static”添加到特征本身
特征类型:'静态{/*…*/}
类型收集fkind;
//版本2:将“static”添加到类型定义中
性状种类{/*…*/}
类型CollectionOfKind=Vec;
我不明白的是:这三种情况的确切区别是什么

我的问题:

为了了解差异,我试图理解其他答案中提到的某些要点。例如,在上面的链接答案2中,我发现了以下我不完全理解的提示:

在这种情况下,
'static
要求底层对象必须是实结构或
&'static
引用,但不允许其他引用

底层对象必须是“真实”结构是什么意思?一个结构怎么可能实现这个特性而不是“真实的”

同样,对于@Shepmaster引用的引用:

必须指定两次生存期:一次用于引用的生存期,另一次用于trait对象本身,因为trait可以为引用实现,如果底层对象是引用,则还必须指定其生存期

老实说,我不明白为什么必须指定两次。我认为trait对象是通过引用实现某个trait的对象来定义的。所以,根据定义,它是一个引用,因此,无论如何,它都有一个生命周期?

新问题的答案 你真的有。我将首先解决较简单的问题,即#2和#3的差异。我希望这是一个具有代表性的例子:

trait-Kind{
fn trait_fn(&self)->u8{0}
}
类型CollectionOfKind1=Vec;
结构α;
Alpha{}的impl-Kind
结构Beta{}
fn main(){
让name=“world.to_string();
//不需要/拥有它自己的一生。
设a=α;
//引用了具有“静态生存期”的内容。
设b1=Beta{name:“hello”};
//引用了生命周期为'name'的内容,
//而不是“静态”。
设b2=Beta{name:&name[..]};
//我们的向量由对的引用组成
//那些本身可能有参考价值的东西!
让mut c1:CollectionOfKind1=Vec::new();
c1.推送(a);
c1.推动(和b1);
//c1.push(&b2);//错误:`name`的寿命不够长
让mut c2:CollectionOfKind2=Vec::new();
c2.推送(a);
c2.推动(和b1);
c2.推(&b2);//万岁
}
这里值得注意的是,生命周期不必相同!你可以写:

type CollectionOfKind2=Vec;
第二件事是
trait Foo:'static
的含义。我不太确定,但我写了一个小例子:

trait Foo:'static{}
fnx(a:&Foo){}
fn main(){
x(&3u8);
}
在编译过程中,使用

必须为对象类型的强制转换实现trait
Foo
“static

基于此,我认为
Foo:'static
只是编写
Foo+'static
的另一种方式。我能想到的主要区别是,它限制了trait在具有非静态生命周期的结构上实现:

struct B{}
有错误吗

声明的生存期界限不满足[…],但生存期参数必须超过静态生存期

原始答案 我知道你已经发现了,但是你可能想更新你的Rust版本。如果我在Playpen上编译您的代码,我会得到一个关于如何修复它的建议:

错误:路径应位于“+”的左侧,而不是“&”类“[E0178]
类型CollectionOfKind=Vec;
^~~~~~~~

这引用了。

以什么方式
和'a Kind+'a
不起作用?@dbaupp:error:应该是
+
左侧的路径,而不是
和'a Kind
[E0178]。然而,我刚刚看到
&'a(Kind+'a)
确实有效!(我可以发誓我以前试过的时候失败了…)。但是我仍然不理解这个生存期界限的影响。我发现你引用的上面的注释也很有用:
你必须指定生存期两次:一次用于引用的生存期,一次用于trait对象本身,因为trait可以为引用实现,如果底层对象是一个引用,那么您也必须指定它的生存期。
@bluenote10我已经用您修改过的问题更新了我的答案。哇,完美的总结,现在这有意义了。谢谢!
// Version 2: Adding 'static to the type definition
trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a (Kind + 'static)>;
// Version 3: Adding the lifetime of the reference to the trait object (?)
trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a (Kind + 'a)>;