代码之家  ›  专栏  ›  技术社区  ›  soupybionics

了解Rust中参数化结构的生命周期

  •  2
  • soupybionics  · 技术社区  · 8 年前

    以下代码

    struct Cat<'a, T> {
        coolness: &'a T,
    }
    

    抱怨说

    error[E0309]: the parameter type `T` may not live long enough
     --> src/main.rs:2:5
      |
    1 | struct Cat<'a, T> {
      |                - help: consider adding an explicit lifetime bound `T: 'a`...
    2 |     coolness: &'a T,
      |     ^^^^^^^^^^^^^^^
      |
    note: ...so that the reference type `&'a T` does not outlive the data it points at
     --> src/main.rs:2:5
      |
    2 |     coolness: &'a T,
      |     ^^^^^^^^^^^^^^^
    

    它使用显式的生存期界限进行编译。当我实例化结构时 T 是一个 &i32 尽管每个引用都有不同的生存期,但代码还是可以编译的。我的理解是编译器看到 & 超过外部 & :

    struct Cat<'a, T>
    where
        T: 'a,
    {
        coolness: &'a T,
    }
    
    fn main() {
        let b = 10;
        {
            let c = &b;
            {
                let fluffy = Cat { coolness: &c };
            }
        }
    }
    

    Cat { coolness: &c } 扩展到 Cat { coolness: &'a &'a i32 } ? 对于更多嵌套引用,内部引用是否也假定相同的生存期等?

    1 回复  |  直到 8 年前
        1
  •  4
  •   Francis Gagné    8 年前

    Cat { coolness: &c } 扩展到 Cat { coolness: &'a &'a i32 } ?

    是的 Cat 以引用结束。这可以通过以下代码编译来演示:

    let fluffy = Cat { coolness: &c };
    fn is_it_a_double_ref(_x: &Cat<&i32>) {}
    is_it_a_double_ref(&fluffy);
    

    然而,每个引用的生存期不一定相同。

    我的理解是,编译器看到内部&超出外部(&A);

    这是正确的。这正是 T: 'a 束缚开始发挥作用。

    生命周期界限一开始有点难以理解。他们对 T . 例如,给定边界 T: 'static ,不包含任何引用或仅包含 'static 参考资料,例如。 i32 &'static str ,满足绑定,而包含- '静态 参考资料,例如。 &'a i32 ,不要,因为 'a: 'static 为false。更一般地说,给定界限 T: 'a ,类型 T 对于每个生存期参数,满足界限if 'x 在…上 T , 'x: 'a 为true(没有生存期参数的类型通常满足该界限)。

    现在回到您的代码。让我们给这些参考资料起一些名字。我们会说 coolness &'fluffy &'c i32 . 'c 是变量的生存期 c 'fluffy 是变量的生存期 fluffy (与直觉相反,生存期编码的是借用的范围,而不是引用的生存期,尽管编译器确实检查借用没有超出引用的生存期)。这意味着 Fluffy Cat<'fluffy, &'c i32> . 是真的吗 &'c i32: 'fluffy ?

    检查是否 &'c i32:'毛茸茸的 是真的,我们需要检查 'c: 'fluffy 是真的。 c:毛茸茸的 是true,因为变量 c 之后超出范围 毛茸茸的 .

    推荐文章