struct InnerA {
}
struct InnerB<'a> {
inner_a: &'a InnerA,
}
struct Outer {
inner_a: InnerA,
inner_b: InnerB,
}
fn main() {
let inner_a = InnerA {};
let inner_b = InnerB {
inner_a: &inner_a,
};
let outer = Outer {
inner_a,
inner_b,
};
println!("OK");
}
我一开始的想法是这样的,outer
持有两个对象,b
持有a
的引用,持有引用需要生命周期我能理解,但是光这样是无法编译过的,因为提示我Outer
的inner_b
字段也需要生命周期,这个我就不太能理解了,Outer
不是持有了inner_b
的所有权吗,为什么还需要生命周期呢
分割线 然后我就改成了这样
struct InnerA {
}
struct InnerB<'a> {
inner_a: &'a InnerA,
}
struct Outer<'b> {
inner_a: InnerA,
inner_b: InnerB<'b>,
}
fn main() {
let inner_a = InnerA {};
let inner_b = InnerB {
inner_a: &inner_a,
};
let outer = Outer {
inner_a,
inner_b,
};
println!("OK");
}
我替Outer
和字段b
声明了生命周期,但是编译还是报错,这个报错我就更无法理解了
error[E0505]: cannot move out of `inner_a` because it is borrowed
--> src/main.rs:18:9
|
14 | inner_a: &inner_a,
| -------- borrow of `inner_a` occurs here
...
18 | inner_a,
| ^^^^^^^ move out of `inner_a` occurs here
19 | inner_b,
| ------- borrow later used here
我传递给b
的不是a
的引用么?为什么下面会报 move out of inner_a
的错误? 是我犯了什么低级错误吗,还是我理解的 Rust 根本就不对。。。
只能来论坛求助了,希望能得到大佬的回复,Rust真的好难啊。。。哭哭
1
共 8 条评论, 1 页
评论区
写评论非常感谢您的回复,我再理一理思路,心智模型还是差了好多
--
👇
Eliot00: 如果允许你移动了a,还保持b对a的引用,就相当于制造了悬垂指针,出现内存bug,所以提示cannot move out of
inner_a
because it is borrowed如果允许你移动了a,还保持b对a的引用,就相当于制造了悬垂指针,出现内存bug,所以提示cannot move out of
inner_a
because it is borrowed--
👇
Eliot00: ```rust struct InnerA { } struct InnerB<'a> { inner_a: &'a InnerA, } struct Outer { inner_a: InnerA, inner_b: InnerB, } fn main() {
}
这段代码里,在a处,
inner_a
持有一个了InnerA实例的所有权,b处,inner_b
借用了inner_a
,但是在c处,此时innner_b
还*“活着”*,手上还有对a的借用,可是inner_a
在c处,他的所有权被outer
拿走了lifetime标记并不能延长变量的生存期,可以理解为
inner_a
被拿去构造Outer
的时候它的生命就到头了,可是inner_b
还在引用它,所以就报错了这里已经被借用了,然后你又需要它的所有权。。。
👇
kaixinbaba: 我知道字面意思,但是不知道怎么改,\尴尬
--
👇
langzi.me: 错误提示不是挺明白的。
inner_a: &inner_a, | -------- borrow of
inner_a
occurs here谢谢谢谢,什么时候用Box 什么时候用 & 。。
--
👇
12101111: 你这样自引用了. 你的第一段代码是错的,是因为InnerB的类型里有生命周期参数, 完整的类型必须加上<'a>. 第二段类型改对了, 但是也是不能编译的, 因为inner_b初始化的时候借用了inner_a, 这时候inner_b的inner_a字段指向栈上的inner_a, 但是后面初始化Outer的时候, 就把inner_a move走了, 这时候inner_b存的inner_a的地址就已经无效了, 所以会报错. 所以先把inner_a放到堆上, 这样inner_a的地址就不会变了.
我知道字面意思,但是不知道怎么改,\尴尬
--
👇
langzi.me: 错误提示不是挺明白的。
inner_a: &inner_a, | -------- borrow of
inner_a
occurs here你这样自引用了. 你的第一段代码是错的,是因为InnerB的类型里有生命周期参数, 完整的类型必须加上<'a>. 第二段类型改对了, 但是也是不能编译的, 因为inner_b初始化的时候借用了inner_a, 这时候inner_b的inner_a字段指向栈上的inner_a, 但是后面初始化Outer的时候, 就把inner_a move走了, 这时候inner_b存的inner_a的地址就已经无效了, 所以会报错. 所以先把inner_a放到堆上, 这样inner_a的地址就不会变了.
错误提示不是挺明白的。
inner_a: &inner_a, | -------- borrow of
inner_a
occurs here