【发布时间】:2021-01-03 01:22:57
【问题描述】:
我对 rust 生命周期的学习过程如下所示(基于 rust 书):
- 我想在引用后面的值超出范围时进行注释
- 通常(并非总是如此!请参阅 .data 部分,即“静态”)值位于
{}块中 - 我们注释块像
't: {…}和例如struct 字段的生命周期类似于&'t ident具有相同的生命周期名称t - 这种理解是错误的。为什么?结构实现者很可能不知道块名称定义,并且同一结构可能有多个块名称定义。
- 所以
't: {…}的定义和&'t ident的用法必须完全独立。 - 编译器可以轻松确定定义,因此用户无需编写
't: {…}。程序员只需要关心&'t ident规范部分。 - 编译器可以分析函数体(在
struct的情况下:使用结构成员)并确定&'t ident部分。 - 这种理解是错误的。为什么?因为有时函数体(或结构成员的使用)尚不可用(例如,特征指定了一个函数,但未来由其他方完成)。
- 因此,
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++"
}
}
这为s2.league 提供error[E0621]: explicit lifetime required in the type of s1 和lifetime 'static required。
我的理解在哪一点上是错误的?提前感谢您对我的包容。
免责声明: help: add explicit lifetime 'static to the type of s1: &'a Stats<'static> 可以在这里工作,但对我来说似乎是错误的。
【问题讨论】: