简体   繁体   English

为什么你会在结构中使用相同的生命周期?

[英]Why would you ever use the same lifetimes for references in a struct?

This question is similar to When is it useful to define multiple lifetimes in a struct? 这个问题类似于什么时候在结构中定义多个生命周期有用? , but hopefully different enough. ,但希望足够不同。 The answer to that question is helpful but focuses on advantages of one approach (using distinct lifetimes for references in struct) but not on drawbacks (if any). 这个问题的答案很有帮助,但侧重于一种方法的优点(对结构中的引用使用不同的生命周期),而不是缺点(如果有的话)。 This question, like that, is looking for guidance on how to choose lifetimes when creating structs. 像这样的问题,正在寻找关于如何在创建结构时选择生命周期的指导。

Call this the tied together version because x and y are required to have the same lifetime: 将此称为捆绑在一起的版本,因为xy需要具有相同的生命周期:

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

and call this the loose version because lifetimes can vary: 并将其称为松散版本,因为生命周期可能会有所不同:

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

The answer to the referenced question gives a clear case where client code can compile/run given the loose version but will fail for the tied together version. 引用问题的答案给出了一个明确的案例,其中客户端代码可以在松散版本的情况下编译/运行,但是对于捆绑在一起的版本将会失败。 Isn't it the case that any client code that works for the tied together version will also work for the loose version and will be guaranteed just as safe (ie safe)? 是不是所有适用于捆绑版本的客户端代码也适用于松散版本并且保证安全 (即安全)? The obverse is not true. 正面不是真的。 The loose version is clearly more flexible from a struct designer perspective. 从结构设计者的角度来看, 松散版本显然更加灵活。 Given it is a good/accepted answer the guidance might be - when using references in a struct always give them distinct lifetimes. 鉴于它是一个好的/可接受的答案,指导可能是 - 当在结构中使用引用时总是给它们不同的生命周期。

What is the drawback to this advice, ignoring the extra typing? 这个建议的缺点是什么,忽略了额外的打字? For example, is there ever benefit to requiring references in a struct have the same lifetime? 例如,在结构中要求引用具有相同的生命周期是否有益处?

is there ever benefit to requiring references in a struct have the same lifetime 要求结构中的引用具有相同的生命周期是否有益处

Yes, and it goes beyond having a struct. 是的,它不仅仅是一个结构。 If lifetimes were always distinct from each other, then you couldn't write this function: 如果生命周期总是彼此不同,那么你就不能写这个函数:

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

Applying to the struct, you could have something like this: 应用于结构,你可以有这样的东西:

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
        }
    }
}

Note that while this compiles, it doesn't return a string that can outlive the structure itself , which is not what was intended. 请注意,虽然这个编译,但它不会返回一个可以比结构本身更长的字符串 ,这不是预期的。 This code fails, even though it should be able to work: 此代码失败,即使它应该能够工作:

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

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

This will work with unified lifetimes: 这将适用于统一的生命周期:

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
        }
    }
}

This is the opposite of the linked answer, which has the comment: 这与链接答案相反,后者的评论如下:

you want to be able to take an aggregate value and split off parts of it after using it 您希望能够获取聚合值并在使用后拆分它的一部分

In this case, we want to take an aggregate value and unify them. 在这种情况下,我们希望获取一个聚合值并统一它们。

In rarer occasions, you may need to thread the needle between distinct and unified lifetimes : 在极少数情况下,您可能需要在不同的和统一的生命周期之间穿针:

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
        }
    }
}

While this is useful when needed, I can't imagine the wailing and gnashing of teeth that would erupt if we had to write it this way every time. 虽然这在需要的时候很有用,但我无法想象如果我们每次都必须这样写的话,会发出嚎叫和咬牙切齿的声音。


ignoring the extra typing 无视额外打字

I wouldn't. 我不会。 Having

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

is definitely better than 肯定比

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

When you aren't benefiting from the extra generic parameters. 当您没有从额外的通用参数中受益时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM