我试图更好地了解Rust的寿命。
struct Name<'a> {
arg: &'a u8,
}
impl<'a> Name<'a> {
fn new1(arg: &'a u8) -> Name<'a> {
Name { arg }
}
fn new2<'b>(arg: &'b u8) -> Name<'b> {
Name { arg }
}
}
Run Code Online (Sandbox Code Playgroud)
是否有功能之间的差异new1
和new2
?我假设,如果会的问题arg
是&self
?在任何情况下都new2
倾向于实现吗?
这两种方法最终完全相同,但值得了解其原因。一路上,我们将了解终身强制
如果第二个生命周期比第一个生命周期短(或者更确切地说,包含在第一个生命周期中),则一个生命周期可以强制进入另一个生命周期。这通常被标记'a: 'b
为意味着生命周期'a
完全包含生命周期'b
。通常的术语是'a
“超越” 'b
。这种强制的原因是,如果需要的话,你总是可以缩短寿命。如果引用在某个生命周期内有效,那么它在较长生命周期中包含的任何较短生命周期内也有效。
那么考虑到这一点,可以采取什么样的论据new1
呢new2
?我们有一个固定的生命周期'a
,因为整个实现在该生命周期中是通用的。但是,new1
不仅可以拿&'a u8
,而且任何&'b u8
如果都'b
可以胁迫'a
。即'b: 'a
和'b
比 长'a
。
new2
略有不同,但最终效果相同。该方法在生命周期内是通用的'b
,可以采用任何&'c u8
if 'c: 'b
。new2
在技术上仍然是通用的'a
,但由于它根本不使用'a
,因此可以忽略。也就是说,忽略通用参数会令人困惑(为什么要使用该参数?),因此最好使用它new1
。
new1
更喜欢它的另一个原因new2
是它更适合Self
. 如果我们尝试将输出更改为Self
impl<'a> Name<'a> {
fn new1(arg: &'a u8) -> Self {
Name { arg }
}
fn new2<'b>(arg: &'b u8) -> Self {
Name { arg }
}
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨。为什么?现在输出必须是Name<'a>
且在 中new2
,我们将返回Name<'b>
。这不能强制执行Name<'a>
except 'b: 'a
,因此我们必须将其添加为'b
:
impl<'a> Name<'a> {
fn new1(arg: &'a u8) -> Self {
Name { arg }
}
fn new2<'b: 'a>(arg: &'b u8) -> Self {
Name { arg }
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,很明显这new1
是优越的,因为它甚至不需要第二个生命周期,但仍然允许完全相同的输入。
归档时间: |
|
查看次数: |
76 次 |
最近记录: |