为何返回块内x的引用编译失败,返回x.clone()的引用却可行?
两段Rust代码的编译差异原因
先看第一段无法编译的代码:
let y = { let x = "foo".to_owned(); &x }; dbg!(y);
这段代码里,x是代码块内部的局部变量,它的生命周期仅限于这个代码块。当代码块执行完毕,x会被Rust自动销毁。如果返回&x,那么y就成了指向已销毁变量的悬垂引用,这会引发内存安全问题,所以Rust的借用检查器直接拒绝编译这段代码。
再看第二段可以正常编译的代码:
let y = { let x = "foo".to_owned(); &x.clone() }; dbg!(y);
这里的核心是x.clone()生成的是一个临时值。Rust有个特殊的生命周期规则:当临时值被引用,且这个引用作为表达式的返回值绑定到外部变量时,临时值的生命周期会被延长,和绑定它的外部变量(也就是y)的生命周期保持一致。
换句话说,x.clone()创建的新String不会随着代码块结束被销毁,而是会被保留到y的生命周期结束,所以y的引用始终指向有效的内存空间,编译器允许这段代码通过。
内容的提问来源于stack exchange,提问作者TSK
相关产品推荐
相关产品推荐

