让两个结构相互引用 - 生锈
having two struct reference each other - rust
我对 Rust 编程还很陌生,我正在尝试将我在 js 中的代码转换为 Rust。
简单的概念如下:
fn main() {
let mut ds=DataSource::new();
let mut pp =Processor::new(&mut ds);
}
struct DataSource {
st2r: Option<&Processor>,
}
struct Processor {
st1r: &DataSource,
}
impl DataSource {
pub fn new() -> Self {
DataSource {
st2r: None,
}
}
}
impl Processor {
pub fn new(ds: &mut DataSource) -> Self {
let pp = Processor {
st1r: ds,
};
ds.st2r = Some(&pp);
pp
}
}
如您所见,我的系统中有两个相互连接的主要模块,我需要每个模块在另一个模块中的引用。
好吧,这段代码当然会抱怨生命周期之类的东西。所以我开始像疯子一样到处乱扔生命周期说明符,即便如此,它仍然抱怨说在“Processor::new”中我不能 return 借用的东西。合法的。但我找不到任何解决方案!无论我如何尝试处理彼此的引用,它都以这个借用错误结束。
那么,有人可以针对这种情况指出解决方案吗?我的应用程序的结构在 Rust 中是否无效,我应该以其他方式进行吗?还是我没有经验的头脑找不到这个技巧?
谢谢。
您尝试做的事情不能用引用和生命周期来表达,因为:
DataSource
必须比Processor
活得长,这样pp.st1r
才能保证有效,
- 和
Processor
必须比 DataSource
活得更长,这样才能保证 ds.st2r
有效。您可能会认为,由于 ds.st2r
是一个 Option
,并且由于 None
变体不包含引用,因此允许 DataSource
具有 None
值 st2r
比任何 Processor
都长,但不幸的是,编译器在编译时无法知道 st2r
是否包含 Some
值,因此必须假设它包含。
您的问题因您需要对 DataSource
的 可变 引用而变得更加复杂,以便您可以一次设置其 st2r
字段当你在 Processor
中也有一个不可变的未完成引用时,Rust 不允许。
您可以通过使用 Rc
(for dynamic lifetime tracking) and RefCell
(用于动态可变性跟踪)切换到动态生命周期和可变性跟踪来使您的代码正常工作:
use std::cell::RefCell;
use std::rc::{ Rc, Weak };
fn main() {
let ds = Rc::new (RefCell::new (DataSource::new()));
let pp = Processor::new (Rc::clone (&ds));
}
struct DataSource {
st2r: Weak<Processor>,
}
struct Processor {
st1r: Rc<RefCell<DataSource>>,
}
impl DataSource {
pub fn new() -> Self {
DataSource {
st2r: Weak::new(),
}
}
}
impl Processor {
pub fn new(ds: Rc::<RefCell::<DataSource>>) -> Rc<Self> {
let pp = Rc::new (Processor {
st1r: ds,
});
pp.st1r.borrow_mut().st2r = Rc::downgrade (&pp);
pp
}
}
请注意,我已将您的 Option<&Processor>
替换为 Weak<Processor>
。可以使用 Option<Rc<Processor>>
,但如果您在没有先将 st2r
设置为 None
的情况下删除对 DataSource
的所有引用,这将有内存泄漏的风险。 Weak<Processor>
的行为或多或少类似于 Option<Rc<Processor>>
,当所有其他引用被删除时,它会自动设置为 None
,确保内存将被正确释放。
我对 Rust 编程还很陌生,我正在尝试将我在 js 中的代码转换为 Rust。
简单的概念如下:
fn main() {
let mut ds=DataSource::new();
let mut pp =Processor::new(&mut ds);
}
struct DataSource {
st2r: Option<&Processor>,
}
struct Processor {
st1r: &DataSource,
}
impl DataSource {
pub fn new() -> Self {
DataSource {
st2r: None,
}
}
}
impl Processor {
pub fn new(ds: &mut DataSource) -> Self {
let pp = Processor {
st1r: ds,
};
ds.st2r = Some(&pp);
pp
}
}
如您所见,我的系统中有两个相互连接的主要模块,我需要每个模块在另一个模块中的引用。
好吧,这段代码当然会抱怨生命周期之类的东西。所以我开始像疯子一样到处乱扔生命周期说明符,即便如此,它仍然抱怨说在“Processor::new”中我不能 return 借用的东西。合法的。但我找不到任何解决方案!无论我如何尝试处理彼此的引用,它都以这个借用错误结束。
那么,有人可以针对这种情况指出解决方案吗?我的应用程序的结构在 Rust 中是否无效,我应该以其他方式进行吗?还是我没有经验的头脑找不到这个技巧?
谢谢。
您尝试做的事情不能用引用和生命周期来表达,因为:
DataSource
必须比Processor
活得长,这样pp.st1r
才能保证有效,- 和
Processor
必须比DataSource
活得更长,这样才能保证ds.st2r
有效。您可能会认为,由于ds.st2r
是一个Option
,并且由于None
变体不包含引用,因此允许DataSource
具有None
值st2r
比任何Processor
都长,但不幸的是,编译器在编译时无法知道st2r
是否包含Some
值,因此必须假设它包含。
您的问题因您需要对 DataSource
的 可变 引用而变得更加复杂,以便您可以一次设置其 st2r
字段当你在 Processor
中也有一个不可变的未完成引用时,Rust 不允许。
您可以通过使用 Rc
(for dynamic lifetime tracking) and RefCell
(用于动态可变性跟踪)切换到动态生命周期和可变性跟踪来使您的代码正常工作:
use std::cell::RefCell;
use std::rc::{ Rc, Weak };
fn main() {
let ds = Rc::new (RefCell::new (DataSource::new()));
let pp = Processor::new (Rc::clone (&ds));
}
struct DataSource {
st2r: Weak<Processor>,
}
struct Processor {
st1r: Rc<RefCell<DataSource>>,
}
impl DataSource {
pub fn new() -> Self {
DataSource {
st2r: Weak::new(),
}
}
}
impl Processor {
pub fn new(ds: Rc::<RefCell::<DataSource>>) -> Rc<Self> {
let pp = Rc::new (Processor {
st1r: ds,
});
pp.st1r.borrow_mut().st2r = Rc::downgrade (&pp);
pp
}
}
请注意,我已将您的 Option<&Processor>
替换为 Weak<Processor>
。可以使用 Option<Rc<Processor>>
,但如果您在没有先将 st2r
设置为 None
的情况下删除对 DataSource
的所有引用,这将有内存泄漏的风险。 Weak<Processor>
的行为或多或少类似于 Option<Rc<Processor>>
,当所有其他引用被删除时,它会自动设置为 None
,确保内存将被正确释放。