当我在单个函数或仅在主函数中使用时,字符串文字的 Rust 引用的行为有所不同

Sam*_*ang 3 string rust

我最近正在学习所有权和生命周期。但我发现字符串文字有一个奇怪的情况。

//! work perfectly

fn foo() -> &'static str {
    let a = "66";
    &a
}

fn main() {
    let b = foo();
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

当我像上面一样使用字符串文字时,它工作得很好。但是当我像下面这样使用它时:

//! broken

fn main() {
    {
        let b;
        {
            let a = "66";
            b = &a;
        }
        println!("{}", b);
    }
}
Run Code Online (Sandbox Code Playgroud)

它坏了,告诉我:

b = &a;
    ^^ borrowed value does not live long enough
Run Code Online (Sandbox Code Playgroud)

这些让我很困惑。为什么它们不同?

use*_*198 8

这两个程序之间的差异来自于自动取消引用。

//! work perfectly

fn foo() -> &'static str {
    let a = "66";
    &a // the type of this expression is not &'static str it is &&'static str
}

fn main() {
    let b = foo();
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

由于 的类型a&'static str的类型&a&&'static str。请注意第二个参考。它是对没有静态生存期的字符串的引用,而不是字符串值。但是,由于foo返回类型为&'static str&a因此自动取消引用a,并且 的类型b被推断为&'static str。在第二个程序中,这种情况不会发生,因为类型不明确,因此 b 被推断为 a,&&'static str它引用的引用仅在块的生命周期内有效。

如果更新第二个程序以显式声明 b 的类型,您将获得相同的效果。

然而,更好的方法是完全不依赖自动取消引用,并使用以下两个程序之一:

fn foo() -> &'static str {
    let a = "66";
    a // note no &
}

fn main() {
    let b = foo();
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

或者

fn main() {
    {
        let b;
        {
            let a = "66";
            b = a; // Again no &
            // In idiomatic code it would probably make sense to inline the
            // assignment, but I have left it in for clarity with the original code
        }
        println!("{}", b);
    }
}
Run Code Online (Sandbox Code Playgroud)