我有两个相互依赖的结构。在 C++ 中,我会使用指针来完成此操作,我正在尝试弄清楚如何在 Rust 中执行此操作。到目前为止,我已经尝试使用 Box 和 Rc,我认为由于 Rc 是一个参考计数器,它应该能够处理这个问题,但它给了我一个错误。
这是一个简单的代码示例:
struct A {
b : Rc<B>
}
struct B {
a : Option<Rc<A>>
}
fn main() {
let mut b = B {
a : None
};
let a = A {
b: Rc::new(b)
};
b.a = Some(Rc::new(a));
}
Run Code Online (Sandbox Code Playgroud)
这是我从中得到的错误:
20 | let mut b = B {
| ----- move occurs because `b` has type `B`, which does not implement the `Copy` trait
...
25 | b: Rc::new(b)
| - value moved here
...
28 | b.a = Some(Rc::new(a));
| ^^^ value partially assigned here after move
Run Code Online (Sandbox Code Playgroud)
在 Rust 中建立这种关系的正确方法是什么?
您不应该Rc::new对一个对象使用两次。正确的做法是使用Rc::new一次,根据需要克隆。更重要的是,为了在ba 后面变异Rc,你应该将它与 结合起来RefCell。
use std::cell::RefCell;
use std::rc::Rc;
struct A {
b: Rc<B>,
}
struct B {
a: RefCell<Option<Rc<A>>>,
}
fn main() {
let b = Rc::new(B {
a: RefCell::new(None),
});
let a = Rc::new(A { b: b.clone() });
*b.a.borrow_mut() = Some(a.clone());
assert!(b.a.borrow().is_some());
}
Run Code Online (Sandbox Code Playgroud)
但即使你这样做,你仍然会发生内存泄漏,这是很糟糕的。更好的方法是使用Weak和Rc::new_cyclic制作循环。
use std::rc::{Rc, Weak};
struct A {
b: Rc<B>,
}
struct B {
a: Weak<A>,
}
fn main() {
let a: Rc<A> = Rc::new_cyclic(|a| A {
b: Rc::new(B { a: a.clone() }),
});
let b: Rc<B> = a.b.clone();
}
Run Code Online (Sandbox Code Playgroud)
这避免了单元的使用和内存泄漏。