【问题标题】:Why returning a reference owned by the current function is allowed in Rust?为什么 Rust 允许返回当前函数拥有的引用?
【发布时间】:2019-09-06 03:09:57
【问题描述】:

我正在学习 Rust 的生命周期/所有权概念,并想解释 Rust (rustc 1.37.0) 中的以下行为。

对于这样的程序:

#[derive(Debug)]
struct Book {
    price: i32,
}

fn main() {
    let book1 = Book {price: 12};
    let cheaper_book = choose_cheaper(&book1);
    println!("{:?}", cheaper_book);
}

fn choose_cheaper(b1: &Book) -> &Book {
    if b1.price < 15 {
        b1
    } else {
        let cheapest_book = Book {price: 0};
        &cheapest_book
    }
}

生锈报告:

17 |   &cheapest_book
   |   ^^^^^^^^^^^^^^ returns a reference to data owned by the current function

我可以理解这个错误,因为变量cheapest_book是价格为0的书的所有者,它会在这个函数结束时被删除,所以返回的引用将在此之后变得无效。但是如果我将choose_cheaper 函数更改为,我很难解释为什么允许以下内容:

fn choose_cheaper(b1: &Book) -> &Book {
    if b1.price < 15 {
        b1
    } else {
        let cheapest_book = &Book {price: 0};
        cheapest_book
    }
}

有人能给我一些启示吗?谢谢。

【问题讨论】:

标签: struct rust initialization lifetime ownership


【解决方案1】:

let cheapest_book = &amp;Book {price: 0}; 行中,Book不是Book 类型的“新”实例。每次调用此函数时,它都会返回对 Book 类型的 same 实例的引用,该引用将存储在可执行文件的只读数据部分(或者,从技术上讲,数据如果它包含 CellAtomicUsize 或类似的部分)。

在这种情况下,我们可以将代码“扩展”为更明确的内容:

static GLOBAL_BOOK: Book = Book { price: 0 };

fn choose_cheaper<'a>(b1: &'a Book) -> &'a Book {
    if b1.price < 15 {
        b1
    } else {
        let cheapest_book = &GLOBAL_BOOK;
        cheapest_book
    }
}

请注意,对GLOBAL_BOOK 的引用实际上可能是&amp;'static Book,但&amp;'a Book 是它的超类型,因此可以将静态引用作为'a 引用返回。

如果这看起来很奇怪,请考虑这正是字符串文字所发生的情况;他们只是没有明确的&amp; 字符:在let foo = "string!"; 之后,foo 是一个&amp;'static str,它引用了可执行文件的只读部分中的一些数据,而不是本地对象。因此,您也可以在返回&amp;'a str 的函数中为任何'a 编写return "string!";

rust 是否会进行这种转换的规则是每当你“构造”一个​​对象时(使用元组语法,或结构或枚举或联合初始化语法,或数字或字符串文字,或它们的任何组合 - 不 函数调用 new() 或任何其他函数)在 &amp; 后面,它们将成为匿名静态。所以实际上&amp;&amp;1_u32 是一个'static 对静态'static 的引用对静态u32 的引用。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-15
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 2020-11-19
  • 2020-06-05
  • 2014-09-13
相关资源
最近更新 更多