了解寿命:最大寿命和“静态”

问题描述

我的防锈寿命学习过程如下(基于防锈书)

  1. 当引用后面的值超出范围时,我想注释
  2. 通常(并非总是如此!请参见.data部分,即“静态”)值存在于{}块内
  3. 我们注释诸如't: {…}之类的代码块,例如结构字段的生存期类似于&'t ident,并且具有相同的生存期名称t
  4. 这种理解是错误的。为什么?块名定义很可能是结构实现者所未知的,并且同一结构可能有多个块名定义。
  5. 因此,定义't: {…}用法&'t ident必须完全独立。
  6. 编译器可以轻松确定定义,因此用户无需编写't: {…}。程序员只需要关心&'t ident规范部分。
  7. 编译器可以分析函数体(如果使用struct:使用结构成员)并确定&'t ident部分。
  8. 这种理解是错误的。为什么?因为有时函数主体(或使用struct成员)尚不可用(例如,一个trait指定一个函数,但将来会由另一方来实现)。
  9. 结果,structfn必须分别在其结构定义或函数签名中完全指定生存期。
  10. 规范大多遵循相同的启发式规则。因此,我们引入了终身淘汰制。它会根据针对最常见用例的规则插入生存期,我们可以随时选择退出

在这一点上,我认为我的理解非常接近其实际运作方式。但是现在,我的理解错了。让我们看一些例子:

#[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 requireds2.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);
}