fn test1(mut u: &User) {
u = & User {
age: 1
};
}
fn test2(mut u: &User) {
let t = User {
age: 1
};
u = & t;
}
上面代码中test1
不会报错,test2
会报下面的错
36 | fn test2(mut u: &User) {
| - let's call the lifetime of this reference `'1`
...
40 | u = & t;
| ----^^^
| | |
| | borrowed value does not live long enough
| assignment requires that `t` is borrowed for `'1`
41 | }
| - `t` dropped here while still borrowed
不理解为什么test1
不报错
1
共 9 条评论, 1 页
评论区
写评论可以写个代码测试下,给u个数据,打印下函数调用前和调用后的值,就会发现编译器做了很多工作。 对以下内容的回复:
我认为可以这样理解,test2中由于显式定义了t,致使后续可以让t失效,就像这样:
而这在test1中无法做到。 注意到这里u的类型一直是&'a User,而'a中是没有t生存期信息的。因此drop(t)时编译器并不会发现t此时在作用域内有一个合法的引用u,不会阻止drop。
同样费解, test1内的user到底是栈上分配的?还是堆上分配的?如果是栈上分配的,那u就应该是悬垂指针,如果是堆上分配那可以不用Box分配堆上数据?难道rust也有栈逃逸操作?
test1() 不报错, 是因为 u 是诞生在 test1() 世界之外的人, u 进入到 test1() 这个世界, 从这个世界获取了一个物品 User, 然后 u 就带着这件物品 User 离开了 test1(). 物品是否销毁, 关键看他在谁手里. 物品的主人被销毁了, 物品跟随主人一起陪葬
test2() 中, t 诞生了, 并且他持有了一个物品 User. 但是 t 只能活在 test2() 中, 所以 test2() 结束后, t 也就不存在了, t 持有的物品 User 就跟着t一起陪葬. 但是, t 试图把他持有的物品 User 借给外面的人 u 最后, 物品 User 已经随着 t 陪葬了, 不存在了. u 只拿到一张空头支票
为了避免这种开空头支票的行为, 编译器就帮助检查出这种不法行为, 予以报错
第一个函数为啥不报错呢?User对象用完应该就被释放了 对以下内容的回复:
test2和上面的是等价的,可以看看Rust教程的第10章第3节,借用检查器部分。
这是一条规则,被引用对象要比引用对象有更长的生命周期。这条规则是为了防止垂悬指针的问题。
第一个
User
是一个常量, 生命周期可以到'static
下面的代码也能编译通过
关注