When is it useful to define multiple lifetimes in a struct?

青春壹個敷衍的年華 提交于 2019-11-26 06:45:31

问题


In Rust, when we want a struct to contain references, we typically define their lifetimes as such:

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

But it\'s also possible to define multiple lifetimes for different references in the same struct:

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

When is it ever useful to do this? Can someone provide some example code that doesn\'t compile when both lifetimes are \'a but does compile when the lifetimes are \'a and \'b (or vice versa)?


回答1:


After staying up way too late, I was able to come up with an example case where the lifetimes matter. Here is the code:

static ZERO: i32 = 0;

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

fn get_x_or_zero_ref<'a, 'b>(x: &'a i32, y: &'b i32) -> &'a i32 {
    if *x > *y {
        return x
    } else {
        return &ZERO
    }
}

fn main() {
    let x = 1;
    let v;
    {
        let y = 2;
        let f = Foo { x: &x, y: &y };
        v = get_x_or_zero_ref(&f.x, &f.y);
    }
    println!("{}", *v);
}

If you were to change the definition of Foo to this:

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

Then the code won't compile.

Basically, if you want to use the fields of the struct on any function that requires it's parameters to have different lifetimes, then the fields of the struct must have different lifetimes as well.




回答2:


Here is another simple example where the struct definition has to use two lifetimes in order to operate as expected. It does not split the aggregate into fields of different lifetimes, but nests the struct with another struct.

struct X<'a>(&'a i32);

struct Y<'a, 'b>(&'a X<'b>);

fn main() {
    let z = 100;
    //taking the inner field out of a temporary
    let z1 = ((Y(&X(&z))).0).0;  
    assert!(*z1 == z);
}

The struct Y has two lifetime parameters, one for its contained field &X, and one for X's contained field &z.

In the operation ((Y(&X(&z))).0).0, X(&z) is created as a temporary and is borrowed. Its lifetime is only in the scope of this operation, expiring at the statement end. But since X(&z)'s lifetime is different from the its contained field &z, the operation is fine to return &z, whose value can be accessed later in the function.

If using single lifetime for Y struct. This operation won't work, because the lifetime of &z is the same as its containing struct X(&z), expiring at the statement end; therefore the returned &z is no longer valid to be accessed afterwards.

See code in the playground.



来源:https://stackoverflow.com/questions/29861388/when-is-it-useful-to-define-multiple-lifetimes-in-a-struct

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!