[英]Why returning a reference owned by the current function is allowed in Rust?
我正在學習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的Book的所有者,並且它將在此函數結束時刪除,因此返回的引用在此之后將變為無效。 但是,對於我來說,很難解釋為什么如果將choose_cheaper
函數更改為以下內容,為什么允許以下操作:
fn choose_cheaper(b1: &Book) -> &Book {
if b1.price < 15 {
b1
} else {
let cheapest_book = &Book {price: 0};
cheapest_book
}
}
可以給我一些啟示嗎? 謝謝。
在這一行中, let cheapest_book = &Book {price: 0};
,則Book
不是 Book
類型的“新”實例。 每次調用此函數時,它都會返回對相同 Book
類型實例的引用,該引用將存儲在可執行文件的只讀數據部分(或者,如果包含Cell
或AtomicUsize
或從技術上講,則存儲在該數據部分)類似)。
在這種情況下,我們可以將代碼“擴展”為更明確的內容:
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
的引用實際上可以是&'static Book
,但&'a Book
是&'a Book
的超類型,因此可以將靜態引用當作是'a
引用來返回。
如果這看起來很奇怪,請考慮一下這正是字符串文字所發生的; 它們只是沒有顯式&
字符: let foo = "string!";
, foo
是&'static str
引用可執行文件的只讀部分中的某些數據,而不是本地對象。 這樣您還可以編寫return "string!";
在函數返回&'a str
為任何'a
。
生銹是否進行此轉換的規則是您“構造”對象時(使用元組語法,結構或枚舉或聯合初始化語法,數字或字符串文字或它們的任意組合- 而不是對new()
函數調用或&
后面的任何其他函數),它們將成為匿名靜態變量。 所以其實&&1_u32
是'static
參考靜態'static
參考靜態u32
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.