为什么 &14 in a = &14 只存在一个语句?
Why does &14 in a = &14 only live one statement?
我不明白为什么会这样:
let mut i = &14;
而这不是:
let mut i;
i = &14;
在这种情况下,为什么 &14
没有自动获取 i
的生命周期? "something = some new thing with lifetime of only one statement" 什么时候有用?
这是 let
行为方式和表达式行为方式之间的边缘情况。基本上,let
是这里的特例。
在第一个示例中,Rust 知道您正在引用堆栈分配的 i32
。
在第二种情况下,您引入了一个绑定,但随后尝试使用赋值表达式来更新该绑定。因为它只是一个正则表达式,它创建的东西会在表达式末尾超出范围,因此,14
这里只有表达式的生命周期,而不是堆栈帧。
我相信 let
有一个普通 =
还没有的特殊情况,其中直接分配给绑定的引用适用于最近的封闭块(大约值在下一个 }
时被销毁),而不是像通常那样只销毁最近的封闭语句(大约,该值在下一个 ;
时被销毁)。这解释了当前的错误消息:
<anon>:3:10: 3:12 error: borrowed value does not live long enough
<anon>:3 i = &14;
^~
<anon>:2:14: 4:2 note: reference must be valid for the block suffix following statement 0 at 2:13...
<anon>:2 let mut i;
<anon>:3 i = &14;
<anon>:4 }
<anon>:3:5: 3:13 note: ...but borrowed value is only valid for the statement at 3:4
<anon>:3 i = &14;
^~~~~~~~
<anon>:3:5: 3:13 help: consider using a `let` binding to increase its lifetime
<anon>:3 i = &14;
^~~~~~~~
也就是说,这也与新的析构函数更改相互作用,其中数据声明的精确排序对于确保引用安全很重要。 &14
表达式当前表示 let tmp = 14; &tmp
,因此进行脱糖会得到
fn main() {
let mut i;
let tmp = 14;
i = &tmp;
}
无法使用
编译
<anon>:4:10: 4:13 error: `tmp` does not live long enough
<anon>:4 i = &tmp;
^~~
<anon>:2:14: 5:2 note: reference must be valid for the block suffix following statement 0 at 2:13...
<anon>:2 let mut i;
<anon>:3 let tmp = 14;
<anon>:4 i = &tmp;
<anon>:5 }
<anon>:3:17: 5:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 3:16
<anon>:3 let tmp = 14;
<anon>:4 i = &tmp;
<anon>:5 }
The RFC 包含很多细节,但是,总而言之,为了确保泛型析构函数的安全,任何带有引用的数据都必须指向严格比自身长寿的东西,其中 "outlives" 被认为是在语句级别。在这种情况下,tmp
是在 i
之后声明的,因此 i
包含指向它的指针是非法的。
顺便说一下,有些更改可能会导致此代码无法编译。 14
是常量数据,所以它可以放在静态内存中,这意味着 &14
可以是 &'static i32
而不仅仅是 &'short_stack_lifetime i32
。代码的两个版本都是有效的。这是RFC issue #827.
我不明白为什么会这样:
let mut i = &14;
而这不是:
let mut i;
i = &14;
在这种情况下,为什么 &14
没有自动获取 i
的生命周期? "something = some new thing with lifetime of only one statement" 什么时候有用?
这是 let
行为方式和表达式行为方式之间的边缘情况。基本上,let
是这里的特例。
在第一个示例中,Rust 知道您正在引用堆栈分配的 i32
。
在第二种情况下,您引入了一个绑定,但随后尝试使用赋值表达式来更新该绑定。因为它只是一个正则表达式,它创建的东西会在表达式末尾超出范围,因此,14
这里只有表达式的生命周期,而不是堆栈帧。
我相信 let
有一个普通 =
还没有的特殊情况,其中直接分配给绑定的引用适用于最近的封闭块(大约值在下一个 }
时被销毁),而不是像通常那样只销毁最近的封闭语句(大约,该值在下一个 ;
时被销毁)。这解释了当前的错误消息:
<anon>:3:10: 3:12 error: borrowed value does not live long enough
<anon>:3 i = &14;
^~
<anon>:2:14: 4:2 note: reference must be valid for the block suffix following statement 0 at 2:13...
<anon>:2 let mut i;
<anon>:3 i = &14;
<anon>:4 }
<anon>:3:5: 3:13 note: ...but borrowed value is only valid for the statement at 3:4
<anon>:3 i = &14;
^~~~~~~~
<anon>:3:5: 3:13 help: consider using a `let` binding to increase its lifetime
<anon>:3 i = &14;
^~~~~~~~
也就是说,这也与新的析构函数更改相互作用,其中数据声明的精确排序对于确保引用安全很重要。 &14
表达式当前表示 let tmp = 14; &tmp
,因此进行脱糖会得到
fn main() {
let mut i;
let tmp = 14;
i = &tmp;
}
无法使用
编译<anon>:4:10: 4:13 error: `tmp` does not live long enough
<anon>:4 i = &tmp;
^~~
<anon>:2:14: 5:2 note: reference must be valid for the block suffix following statement 0 at 2:13...
<anon>:2 let mut i;
<anon>:3 let tmp = 14;
<anon>:4 i = &tmp;
<anon>:5 }
<anon>:3:17: 5:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 3:16
<anon>:3 let tmp = 14;
<anon>:4 i = &tmp;
<anon>:5 }
The RFC 包含很多细节,但是,总而言之,为了确保泛型析构函数的安全,任何带有引用的数据都必须指向严格比自身长寿的东西,其中 "outlives" 被认为是在语句级别。在这种情况下,tmp
是在 i
之后声明的,因此 i
包含指向它的指针是非法的。
顺便说一下,有些更改可能会导致此代码无法编译。 14
是常量数据,所以它可以放在静态内存中,这意味着 &14
可以是 &'static i32
而不仅仅是 &'short_stack_lifetime i32
。代码的两个版本都是有效的。这是RFC issue #827.