这个问题类似于When is it useful to define multiple lifetimes in a struct?,但希望足够不同.这个问题的答案很有帮助,但重点是一种方法的优点(在struct中使用不同的生命周期进行引用),而不是缺点(如果有的话).像这样的问题,是在寻找如何在创建 struct 时 Select 生命周期的指导.

将其称为tied together版本,因为xy需要具有相同的生存期:

struct Foo<'a> {
    x: &'a i32,
    y: &'a i32,
}

将其称为loose版本,因为生命周期可能会有所不同:

struct Foo<'a, 'b> {
    x: &'a i32,
    y: &'b i32,
}

参考问题的答案给出了一个明确的例子,即客户机代码在给定loose版本的情况下可以编译/运行,但在给定tied together版本的情况下会失败.任何适用于tied together版本的客户端代码都适用于loose版本,并且保证just as safe(即安全),这不是吗?正面不是真的.从struct designer的Angular 来看,loose版本显然更灵活.如果这是一个好的/可接受的答案,那么指导可能是——在 struct always中使用引用时,给它们不同的生存期.

这个建议的缺点是什么,忽略了额外的输入?例如,一个 struct 中有requiring个引用具有相同的生命周期,这有什么好处吗?

推荐答案

要求 struct 中的引用具有相同的生存期有什么好处吗

是的,它不仅仅是一个 struct .如果生命周期总是彼此不同,则无法编写此函数:

fn foo<'a, 'b>(a: &'a str, b: &'b str) -> &str {
    // What lifetime to return?
    if (global_random_number() == 42) {
        a
    } else {
        b
    }
}

应用于struct,可以有如下内容:

struct EvenOrOdd<'a, 'b> {
    even: &'a str,
    odd: &'b str,
}

impl<'a, 'b> EvenOrOdd<'a, 'b> {
    fn do_it(&self, i: u8) -> &str {
        if i % 2 == 0 {
            self.even
        } else {
            self.odd
        }
    }
}

请注意,虽然这是编译,但它是doesn't return a string that can outlive the structure itself,这不是预期的.此代码失败,即使它应该能够工作:

fn foo<'a, 'b>(a: &'a str, b: &'b str) {
    let result = { EvenOrOdd { even: a, odd: b }.do_it(42) };

    println!("{}", result);
}

这将适用于统一的生命周期:

struct EvenOrOdd<'a> {
    even: &'a str,
    odd: &'a str,
}

impl<'a> EvenOrOdd<'a> {
    fn do_it(&self, i: u8) -> &'a str {
        if i % 2 == 0 {
            self.even
        } else {
            self.odd
        }
    }
}

这与链接答案相反,链接答案中有这样的 comments :

您希望能够获取一个聚合值,并在使用该值后将其拆分

在这种情况下,我们要取一个聚合值,并将其设置为unify.

在罕见的情况下,您可能需要在不同和统一的生命周期之间穿针引线:

struct EvenOrOdd<'a, 'b: 'a> {
    even: &'a str,
    odd: &'b str,
}

impl<'a, 'b> EvenOrOdd<'a, 'b> {
    fn do_it(&self, i: u8) -> &'a str {
        if i % 2 == 0 {
            self.even
        } else {
            self.odd
        }
    }
}

虽然这在需要的时候很有用,但我无法想象如果我们每次都这样写的话会爆发出怎样的哀嚎和咬牙切齿.


忽略额外的打字

我不会的,有

foo<'a>(Bar<'a>)

绝对比

foo<'a, 'b', 'c, 'd>(Bar<'a, 'b', 'c, 'd>)

当你不能从额外的泛型参数中获益时.

Rust相关问答推荐

使用Rust s serde_json对混合数据类型进行优化'

何时可以在Rust中退出异步操作?

带扫描的铁 rust 使用滤镜

如果包名称与bin名称相同,并且main.ars位于工作区的同一 crate 中,则无法添加对lib.ars的依赖

`Pin`有没有不涉及不安全代码的目的?

使用 select 处理 SIGINT 和子等待!无阻塞

如何返回 struct 体中向量的切片

如何以与平台无关的方式将OsString转换为utf-8编码的字符串?

我们可以在 Rust 切片中使用步骤吗?

将引用移动到线程中

Google chrome 和 Apple M1 中的计算着色器

Rust 为什么被视为borrow ?

缺失serde的字段无法设置为默认值

Rust与_有何区别?

简单 TCP 服务器的连接由对等重置错误,mio 负载较小

如何递归传递闭包作为参数?

当 `T` 没有实现 `Debug` 时替代 `unwrap()`

有没有办法阻止 rust-analyzer 使非活动代码变暗?

为什么这个闭包没有比 var 长寿?

在 Rust 中组合特征的不同方法是否等效?