我有一些包含一些数据的结构,如下所示:
struct A {
// Some data
}
struct B<'s> {
a: &'s mut A
c: C<'s>
}
impl<'s> B<'s> {
fn new(a: &'s mut A) -> B<'s> {
let c = C::new();
B { a, c }
}
fn extract_c(self) -> C<'s> {
self.c
}
}
struct C<'s> {
// Some other data not referencing A in any way
}
我还有创建和修改所述结构的函数,如下所示:
fn modify(b: &mut B) {
// Modifies b.a and b.c
}
fn construct_c<'s>(a: &'s mut A) -> C<'s> {
let mut b = B::new(a); // C is created in B::new
modify(&mut b);
b.extract_c()
}
我想在其他地方使用
construct_c
,这样我可以在获得调用结果后再次引用 A ,如下所示:
fn main() {
let mut a = A::new();
let c = construct_c(&mut a); // First mutable borrow of `a`
println!("{a}"); // Second borrow of `a`
let result = do_sth_with_c(c); // Move of `c`
do_sth_with_a(a);
// Some other code...
}
但是,当我尝试这样做时,编译器说当我调用
do_sth_with_c
时,我正在使用 a
的第一个可变借用,即使 c
不保存对提供给 a
的引用construct_c
。
当我删除
println!("{a}");
和 do_sth_with_a
时,代码可以编译,但我确实需要打印该信息并在调用 do_sth_with_c
之前执行此操作。有没有办法告诉编译器 C
对 a
的引用一无所知,并且在调用 construct_c
后创建新引用是安全的?
编辑: 当我用
&mut A
替换所有引用 Rc<RefCell<A>>
时,代码将编译。但是有没有另一种方法而不使用 Rc
和 RefCell
?
您在关于
C
的评论中写道,“其他一些数据未以任何方式引用 A
”。但是通过使用相同的生命周期,您可以告诉编译器它们“是”相关的。所以,改变你的定义
struct B<'s> {
a: &'s mut A
c: C<'s>
}
fn construct_c<'s>(a: &'s mut A) -> C<'s> {
let mut b = B::new(a);
modify(&mut b);
b.extract_c()
}
到
struct B<'s, 'c> {
a: &'c mut A
c: C<'c>
}
fn construct_c<'s, 'c>(a: &'s mut A) -> C<'c> {
let mut b = B::new(a);
modify(&mut b);
b.extract_c()
}
现在每个生命周期都可以独立变化,特别是,现场的生命周期
c
允许长于
'a
。也就是说,我怀疑您在未显示的部分中可能还有更多问题。令人怀疑的是 C
有生命周期,但它是用无参数
new()
创建的。值得怀疑的是,调整后,construct_c()
采用的是不受约束的生命周期参数 'c
,该参数不会出现在任何输入中。 C
类型借用了什么数据?为了正确使用生命周期,你必须有这个问题的答案。您可能会尝试使用引用,其中拥有的数据会更好。