为什么生命周期检查在 Vec::as_slice 和数组的强制之间不同?

Why lifetime check differs between Vec::as_slice and array's coercence?

最小代码:

fn foo() {
    let vector = vec![1u8, 2u8];
    let a = &vector.as_slice()[0];
    drop(vector);
    let b = a;
}

fn bar() {
    let array = [1u8, 2u8];
    let a = &array[0];
    drop(array);
    let b = a;
}

编译上述代码时,foo编译不通过,bar可以编译

在函数foo中,a借用了vector,所以我删除vector后,就无法再访问a了。

不过,我觉得bar的情况也是一样的,但是bar可以顺利通过编译。不知道为什么。

这并不特定于向量和数组。 一旦 Rust 可以证明一个值是编译时已知的常量,它就会认为它具有静态生命周期(并且在这种情况下 drop 没有任何影响,因为该值将永远存在)。 参见

我用一个放在变量中的简单常量 (binding) 和盒装版本扩展了您的示例;这显示了与您在向量和数组之间注意到的完全相同的区别(平凡常量与动态分配的值)。

fn test_vec() {
    let src = vec![10u8, 20u8];
    let a = &src[0];
    // drop(src); // rejected by compiler
    let b = a;
    println!("{:?}", b);
}

fn test_array() {
    let src = [10u8, 20u8];
    let a = &src[0];
    drop(src);
    let b = a;
    println!("{:?}", b);
}

fn test_box() {
    let src = Box::new(10u8);
    let a = &src;
    // drop(src); // rejected by compiler
    let b = a;
    println!("{:?}", b);
}

fn test_var() {
    let src = 10u8;
    let a = &src;
    drop(src);
    let b = a;
    println!("{:?}", b);
}

fn main() {
    test_vec();
    test_array();
    test_box();
    test_var();
}

不可变数组文字具有静态生命周期。在这种情况下,删除局部变量 array 并没有真正做任何事情——当二进制文件被加载时,数据被映射到内存中,并且它将在程序的运行期间保留在那里,所以引用仍然有效。你不能再通过 array 变量访问内存了。

矢量情况非常不同。创建一个新的vector会在运行时在堆上动态分配内存,drop()会再次释放那块内存,所以引用就失效了。