问题描述
我的防锈寿命学习过程如下(基于防锈书)
- 当引用后面的值超出范围时,我想注释
- 通常(并非总是如此!请参见.data部分,即“静态”)值存在于
{}
块内 - 我们注释诸如
't: {…}
之类的代码块,例如结构字段的生存期类似于&'t ident
,并且具有相同的生存期名称t
- 这种理解是错误的。为什么?块名定义很可能是结构实现者所未知的,并且同一结构可能有多个块名定义。
- 因此,定义
't: {…}
和用法&'t ident
必须完全独立。 - 编译器可以轻松确定定义,因此用户无需编写
't: {…}
。程序员只需要关心&'t ident
规范部分。 - 编译器可以分析函数体(如果使用
struct
:使用结构成员)并确定&'t ident
部分。 - 这种理解是错误的。为什么?因为有时函数主体(或使用struct成员)尚不可用(例如,一个trait指定一个函数,但将来会由另一方来实现)。
- 结果,
struct
和fn
必须分别在其结构定义或函数签名中完全指定生存期。 - 规范大多遵循相同的启发式规则。因此,我们引入了终身淘汰制。它会根据针对最常见用例的规则插入生存期,我们可以随时选择退出。
在这一点上,我认为我的理解非常接近其实际运作方式。但是现在,我的理解错了。让我们看一些例子:
#[derive(Debug)]
struct Stats {
league: &str,}
const NAME: &str = "rust";
fn more_difficult_league(s1: &Stats,s2: &Stats) -> &str {
if s1.league == s2.league {
s1.league
} else if s1.league == "PHP" {
s2.league
} else {
"C++"
}
}
fn main() {
let mut st = Stats { league: name };
let dleague = more_difficult_league(&st,&st);
println!("{}",dleague);
}
很明显,我省略了任何生命周期规范。
-
结构字段的生存期要么是程序的整个持续时间(
'static
),要么长于结构的长度(Stats<'a>
和league: &'a str
) -
在函数/方法中,我们可能会获得具有生存期
'a
,'b
,'c
等的引用。返回值的生命周期是多少?- 要么是某个静态值(
'static
) - 要么总是相同的特定生存期(例如
'c
) - 要么是一个特定的生存期,要么在编译或运行时就知道了。对于编译器,我们必须指定最坏情况的生存期
max('a,'b,'c,…)
。据我所知,可以通过给每个引用都相同的寿命来做到这一点。
- 要么是某个静态值(
这似乎适用于以下人为设计的较短函数:
fn more_difficult_league<'a>(s1: &'a Stats,s2: &'a Stats) -> &'a str {
if s1.league == s2.league {
s1.league
} else {
s2.league
}
}
如果我们添加一些返回值'static
,则最坏情况的生存期是max('a,'static)
,大概是'static
:
fn more_difficult_league<'a>(s1: &'a Stats,s2: &'a Stats) -> &'static str {
if s1.league == s2.league {
s1.league
} else if s1.league == "PHP" {
s2.league
} else {
"C++"
}
}
这为error[E0621]: explicit lifetime required in the type of s1
给出了lifetime 'static required
和s2.league
。
我的理解在哪一点错?预先感谢您与我联系。
免责声明: help: add explicit lifetime 'static to the type of s1: &'a Stats<'static>
在这里适用,但对我来说似乎是错误的。
解决方法
我将按照以下规定更改您的代码。
more_difficult_league()
的结果代替假装
具有静态寿命(当我们引用s1
时情况并非如此)
或s2
,编译器对此表示抱怨),我们可以介绍一下
为此结果添加一个新的生命周期注释,并指定
参数的生存期必须超过此结果(
where
子句)。
#[derive(Debug)]
struct Stats<'a> {
league: &'a str,}
const NAME: &str = "rust";
fn more_difficult_league<'a,'b,'c>(
s1: &'a Stats,s2: &'b Stats,) -> &'c str
where
'a: 'c,'b: 'c,{
if s1.league == s2.league {
s1.league
} else if s1.league == "PHP" {
s2.league
} else {
"C++"
}
}
fn main() {
let st = Stats { league: NAME };
let dleague = more_difficult_league(&st,&st);
println!("{}",dleague);
}