关于rust生命期的一个问题,有个地方不太理解,书上也没有说的很清楚,想咨询各位
1. 运行环境
rust
3). 当前系统
rust编译器
4). 业务环境
无
5). 相关软件版本
无
2. 问题描述?
#[derive(Debug)]
struct Diff<’t,’s> {
a: &’t i32,
b: &’s i32,
}
fn diff_life() {
let a1 = 12;
let d;
{
let b1 = 23;
d = Diff{a: &a1, b: &b1};
println!(“d.b:{}”, d.b);
} // 1
println!(“d.a:{}”, d.a); // 2
}
虽然在1的位置,b1已经结束了生命期, 但是a1还是有效的, d.a 引用了a1, 且d.a 和d.b 是不同的生命期,那我在2的位置,访问d.a 为什么不可以?
编译器提示 “因为在1位置释放了b1, 但是仍在2位置借用了”。 2的位置我只是借用了a1而已。
3. 您期望得到的结果?
我认为应该编译通过,但实际上报错
4. 您实际得到的结果?
报错信息如下:
55 | let b1 = 23;
| – binding b1
declared here
56 | d = Diff{a: &a1, b: &b1};
| ^^^ borrowed value does not live long enough
57 | println!(“b:{}”, d.b);
58 | }
| - b1
dropped here while still borrowed
59 | println!(“a:{}”, d.a);
| — borrow later used here
要不要加群?
是d借用了,d结构体是个整体吧,又不是你不访问b属性,b属性就不存在了
d
持有了b1
的引用,b1
就是被借用状态。这个排版看得头疼
访问借用值在此之前已经被释放了
有两个隐含的生命周期的关系,局部变量 a 要比 &a 活的长。 其次,结构体里面的引用都要比结构体本身活的长。 满足这样的一定是对的。但是在这个具体的情况里面,编译器还没有那么智能。可以分析清楚结构体里面每一个域都是否合法有效。它需要整个结构体都合法有效
建议在看看Rust的生命周期,其实这东西是给编译器看的,不是给人看的。你可以理解他就是一个标记,标记你引用的数据不允许比源值活的还要久。你这儿最明显的问题就是 d变量的赋值(d = Diff{a: &a1, b: &b1};), d是什么,是一个结构体并且是一个整体,你不能把一个整体当作两个引用来理解。结尾你打印 d 这个变量 看看就明白了
虽然你在2处只使用了
a1
,但是Diff这个结构体里面其实是持有了{let b1 = 23;}
这个作用域里面的b1的引用,但是b1值所在的作用域已经结束,持有的引用也就无效了。