【问题标题】:Why can I return a reference to a local literal but not a variable?为什么我可以返回对本地文字的引用而不是变量?
【发布时间】:2018-10-24 23:43:37
【问题描述】:

为什么这段代码会编译?

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

fn main() {
    let _it = get_iter();
}

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

【问题讨论】:

    标签: reference rust borrow-checker


    【解决方案1】:

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

    让我们看看这段代码:

    fn foo() -> &'static [i32] {
        &[1, 2, 3]
    }
    

    这行得通!

    前段时间,RFC 1414: Rvalue Static Promotion 被合并:“将 constexpr 右值提升为静态内存而不是堆栈槽中的值”。这意味着基本上你写的所有文字都可以永远存在。因此,let _: &amp;'static i32 = &amp;42; 之类的东西也可以使用!

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

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

    这里我们得到“v 寿命不够长”错误。

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

    fn promote_integer() -> &'static i32 {
        &42
    }
    
    fn promote_float() -> &'static f64 {
        &42.42
    }
    
    fn promote_str() -> &'static str {
        "Hello World!"
    }
    
    struct Foo(char);
    
    fn promote_struct() -> &'static Foo {
        &Foo('x')
    }
    

    除了文字之外,这也适用于标准库but these were likely a mistake 中的微小 数量的函数。判断任意const函数的结果是否可以自动提升为static仍然是open topic

    【讨论】:

    • 看来const 变量已经过时了:p
    • @Boiethios 这是一个有趣的想法。您是否找到了可以链接的讨论?
    • @Boiethios 他们并没有过时。这仅适用于文字。有时您需要一个必须计算的 const。
    • @Boiethios 将数据存储在静态内存中存在一些缺点,尤其是在数据很大并且在程序的整个生命周期中不需要的情况下。在某些时候你应该选择接受这种行为。
    • @Alexey 是的,这就是语言模型所说的。但是,优化器仍然可以在以后内联该值。
    猜你喜欢
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    相关资源
    最近更新 更多