[英]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.