了解生命周期:最大生命周期和“静态”
Posted
技术标签:
【中文标题】了解生命周期:最大生命周期和“静态”【英文标题】:Understanding lifetimes: max lifetime and 'static 【发布时间】: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>
可以在这里工作,但对我来说似乎是错误的。
【问题讨论】:
【参考方案1】:我会按照下面提供的方式更改您的代码。
而不是假装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);
【讨论】:
附加问题:您认为我的陈述“据我所知,这可以通过给每个引用相同的生命周期来完成”是正确的吗? @meisterluk 我想是的,只要您在函数代码中不与此相矛盾(例如返回静态 str)。 这是有道理的。谢谢!以上是关于了解生命周期:最大生命周期和“静态”的主要内容,如果未能解决你的问题,请参考以下文章