为什么我可以返回对本地文字但不是变量的引用?

Fre*_*ios 18 reference rust borrow-checker

为什么这段代码会编译?

fn get_iter() -> impl Iterator<Item = i32> {
    [1, 2, 3].iter().map(|&i| i)
}

fn main() {
    let _it = get_iter();
}
Run Code Online (Sandbox Code Playgroud)

[1, 2, 3]是一个局部变量并iter()借用它.此代码不应编译,因为返回的值包含对局部变量的引用.

Luk*_*odt 31

在您的示例中,[1, 2, 3]不被视为局部变量,而是作为静态变量!

我们来看看这段代码:

fn foo() -> &'static [i32] {
    &[1, 2, 3]
}
Run Code Online (Sandbox Code Playgroud)

这有效!

前段时间,RFC 1414:Rvalue Static Promotion被合并:"将constexpr rvalues提升为静态内存中的值而不是堆栈槽".这意味着你写的基本上所有文字都可以永远存在.因此,事情let _: &'static i32 = &42;也有效!

如果我们避免使用文字数组,我们可以看到预期的错误:

fn bar() -> impl Iterator<Item = i32> {
    vec![1, 2, 3].iter().map(|&i| i)
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们得到" v不够长寿"的错误.

这不仅限于整数或数组; 它广泛适用于任何仅由文字组成的文字:

fn promote_integer() -> &'static i32 {
    &42
}
Run Code Online (Sandbox Code Playgroud)
fn promote_float() -> &'static f64 {
    &42.42
}
Run Code Online (Sandbox Code Playgroud)
fn promote_str() -> &'static str {
    "Hello World!"
}
Run Code Online (Sandbox Code Playgroud)
struct Foo(char);

fn promote_struct() -> &'static Foo {
    &Foo('x')
}
Run Code Online (Sandbox Code Playgroud)

除了文字之外,这也适用于标准库中的少量功能,但这些可能是错误的.决定是否const可以自动提升任意函数的结果static仍然是一个开放的主题.

  • @Boiethios他们没有过时.这仅适用于文字.有时你需要一个必须计算的const. (4认同)
  • @Boiethios将数据存储在静态内存中有一些缺点,特别是如果数据很大,并且在程序的完整生命周期内不需要.肯定有时候你应该选择这种行为. (4认同)
  • @Alexey 是的,这就是语言模型所说的。但是,优化器仍然可以稍后内联该值。 (2认同)