对从函数返回的临时值的引用
Reference to temporary returned from a function
我在尝试回答 this question 时遇到了这个谜题。
如何/为什么编译:
#[derive(Debug,Default)]
struct Foo {
i: i32
}
#[derive(Debug)]
struct Bar<'a> {
foo: &'a Foo
}
impl<'a> Default for Bar<'a> {
fn default() -> Self {
Bar {
foo: &Foo{ i: 25 }
}
}
}
fn main() {
let bar : Bar = Default::default();
println!("{:?}", bar);
}
我们创建了一个 Bar
的实例,其中包含对 Foo
的引用,但谁拥有 Foo
?它是在 default()
函数中匿名创建的,所以我期待一个错误,指出对它的引用超出了它的范围。
如果我更改 default()
实现,则会收到预期的错误:
fn default() -> Self {
let foo = Foo{ i: 25 };
Bar {
foo: &foo
}
}
error[E0515]: cannot return value referencing local variable `foo`
--> src/main.rs:15:9
|
15 | / Bar {
16 | | foo: &foo
| | ---- `foo` is borrowed here
17 | | }
| |_________^ returns a value referencing data owned by the current function
我阅读了参考文献中与 temporary scopes 相关的部分 - 我没有发现临时对象的范围可以超出函数范围的任何情况。
这是由于 Constant Promotion:
Promotion of a value expression to a 'static
slot occurs when the expression could be written in a constant, borrowed, and dereferencing that borrow where the expression was originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the resulting value does not contain interior mutability or destructors (these properties are determined based on the value where possible, e.g. &None
always has the type &'static Option<_>
, as it contains nothing disallowed).
我在尝试回答 this question 时遇到了这个谜题。
如何/为什么编译:
#[derive(Debug,Default)]
struct Foo {
i: i32
}
#[derive(Debug)]
struct Bar<'a> {
foo: &'a Foo
}
impl<'a> Default for Bar<'a> {
fn default() -> Self {
Bar {
foo: &Foo{ i: 25 }
}
}
}
fn main() {
let bar : Bar = Default::default();
println!("{:?}", bar);
}
我们创建了一个 Bar
的实例,其中包含对 Foo
的引用,但谁拥有 Foo
?它是在 default()
函数中匿名创建的,所以我期待一个错误,指出对它的引用超出了它的范围。
如果我更改 default()
实现,则会收到预期的错误:
fn default() -> Self {
let foo = Foo{ i: 25 };
Bar {
foo: &foo
}
}
error[E0515]: cannot return value referencing local variable `foo`
--> src/main.rs:15:9
|
15 | / Bar {
16 | | foo: &foo
| | ---- `foo` is borrowed here
17 | | }
| |_________^ returns a value referencing data owned by the current function
我阅读了参考文献中与 temporary scopes 相关的部分 - 我没有发现临时对象的范围可以超出函数范围的任何情况。
这是由于 Constant Promotion:
Promotion of a value expression to a
'static
slot occurs when the expression could be written in a constant, borrowed, and dereferencing that borrow where the expression was originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the resulting value does not contain interior mutability or destructors (these properties are determined based on the value where possible, e.g.&None
always has the type&'static Option<_>
, as it contains nothing disallowed).