假设一个函数返回一个对局部变量的悬空引用:
fn foo<'a>() -> &'a i32 {
let i = 2;
&i
}
fn main() { }
字符串
Rust注意到了这一点,并引发了一个错误。
添加寿命:
fn foo<'a>() -> &'a i32 {
'b: {
let i = 2; // i has lifetime 'b
&'c i
}
}
型
Rust推断'c = 'b
,因为&i
引用i
。此外,'a
被示例化为'c
,因此'b
,因为返回类型是&'a i32
,返回值是&'c i32
。我不明白为什么这里会发生错误,因为所有生命周期都可以用具体值示例化,而不会有任何不匹配。
如果main
是
fn main() {
'd: {
let i_ref: &'d i32 = foo(); // foo() has lifetime 'b
}
}
型
那么我们仍然会有'a = 'c = 'b
,但是在main
中有一个生命周期不匹配,因为'b
不包含'd
。在这种情况下,我会期望一个错误。
在第一种情况下,Rust是如何在没有调用foo
的情况下检测到悬空引用的?
1条答案
按热度按时间arknldoa1#
所有传递给非Java函数的生命周期必须对整个函数体有效-生命周期不能在函数执行期间自发存在或无效。
此规则自动排除返回局部引用,因为它们的生存期实际上正好在函数返回之前结束。
(异步函数有点不同--在后台,它们返回一个不透明的未来对象,可能包含也可能不包含引用。但它们仍然阻止返回对堆栈分配变量的引用。)
换一种方式思考:
foo<'a>() -> &'a i32
让调用者选择它想要的任何生存期,只要(不存在的)参数的生存期与返回值匹配。我可以想象调用foo::<'static>()
,根据函数签名的规则,它必须被接受,但显然对于返回局部变量的函数无效。