Self { Self {} -6ren">
gpt4 book ai didi

rust - 如何使从对象到其孙子的生命周期约束 "pass through"?

转载 作者:行者123 更新时间:2023-12-05 01:23:48 25 4
gpt4 key购买 nike

我正在对生命周期和借用检查器进行一些实验。想象一下第一个结构:

struct First {}

impl First {
fn new() -> Self {
Self {}
}

fn second(&self) -> Second {
Second::new(self)
}

fn hello(&self) {
println!("Hello");
}
}

第二个,它有一个依赖于 First 的生命周期约束:

struct Second<'a> {
owner: &'a First,
}

impl<'a> Second<'a> {
fn new(owner: &'a First) -> Self {
Self { owner }
}

fn hello(&self) {
self.owner.hello();
}
}

上面的代码工作得很好:Second 是由 First 创建的,它不能比 First 长。

问题

现在让我们修改 Second 以便它可以创建第三个结构 Third:

struct Second<'a> {
owner: &'a First,
}

impl<'a> Second<'a> {
fn new(owner: &'a First) -> Self {
Self { owner }
}

fn third(&self) -> Third {
Third::new(self.owner)
}

fn hello(&self) {
self.owner.hello();
}
}

Third 本身,它也依赖于 First:

struct Third<'a> {
owner: &'a First,
}

impl<'a> Third<'a> {
fn new(owner: &'a First) -> Self {
Self { owner }
}

fn hello(&self) {
self.owner.hello();
}
}

我想,当创建 Third 的实例时,它会依赖于 First,但事实并非如此。实际上Third依赖于Second:

fn main() {
let f = First::new();
let t = {
let sss = f.second();
sss.third() // error: sss does not live long enough
};
}

那么,我怎样才能使生命周期约束从 First“通过”到 Third

Full playground .

最佳答案

Rust 有如何推断函数生命周期的规则:lifetime elision rules .

这些规则规定:

  • Each elided lifetime (i.e. a type that should had have a lifetime, but doesn't, like &T that is actually &'a T) in the parameters becomes a distinct lifetime parameter.
  • If there is exactly one lifetime used in the parameters (elided or not), that lifetime is assigned to all elided output lifetimes.

In method signatures there is another rule

  • If the receiver has type &Self or &mut Self, then the lifetime of that reference to Self is assigned to all elided output lifetime parameters.

我们以First::second()为例举个例子。它的签名是:

fn second(&self) -> Second

或者,显式省略所有生命周期(顺便说一下,显式省略所有不在引用上的生命周期被认为是一种很好的做法,例如本例中的 Second<'_>):

fn second(&'_ self) -> Second<'_>

所以根据规则#1,我们分配一个新的生命周期,我们称之为'a , 至 &self :

fn second<'a>(&'a self) -> Second<'_>

现在,根据规则 #3,我们选择 'a对于 Second<'_> :

fn second<'a>(&'a self) -> Second<'a>

也就是说,我们返回Second与对 self 的引用具有相同的生命周期.

现在让我们把它应用到Second::third() ...

fn third(&self) -> Third
// Becomes
fn third<'b>(&'b self) -> Third<'b> // Lifetime `'a` is already used

但这不是我们想要的!我们想要结果 Third取决于我们包含的生命周期 First例如,不在 &self 的生命周期内!所以我们真正需要的是使用Third<'a> :

fn third(&self) -> Third<'a> { ... }

现在it works beautifully .

关于rust - 如何使从对象到其孙子的生命周期约束 "pass through"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71841611/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com