这是一个定义结构的Rust伪代码片段:
struct A {
a : *B;
b : *B;
pub c : *B;
}
(指针是C指针,不确定它们是否应该是Box
或其他内容。)此处c
始终设置为a
或b
,所有访问都将通过c
;为A
定义的辅助方法将设置c = a
或c = b
。
Rust-y的做法是什么?我的第一次尝试使用了a,b: RefCell<Box<B>>
和c:Box<B>
,其中c
始终borrow
用于其中一个。但后来我在定义new
时遇到了障碍:
new(b1: B, b2: B) -> A {
let acell = RefCell::new(Box::new(b1)),
A { a: acell,
b: RefCell::new(Box::new(b2)),
c: *acell.borrow() }
}
这不起作用,因为acell
&#34;活得不够长&#34; (在new()
结尾处死亡,而不是在返回时逃脱)。
答案 0 :(得分:2)
一个简单的解决方案:
struct A {
a: B,
b: B,
c: u32,
}
impl A {
pub fn new(a: B, b: B) -> A { A { a: a, b: b, c: 0 } }
pub fn switch(&mut self) { self.c += 1; self.c %= 2; }
pub fn get(&self) -> &B {
match self.c {
0 => self.a,
1 => self.b,
_ => unreachable!(),
}
}
}
我们只是通过不对同一个对象进行多次引用来解决问题;这让我们变得安全。语法有一点小小的牺牲,但除此之外它在性能方面应该是不明显的。
unsafe
解决方案:
struct A {
a: *mut B,
b: *mut B,
c: *mut B,
_marker: PhantomData<B>,
}
impl A {
pub fn new(a: B, b: B) -> A {
A {
a: Box::new(a).into_raw(),
b: Box::new(b).into_raw(),
c: a,
_marker: PhantomData,
}
}
pub fn switch(&mut self) {
self.c =
if self.a == self.c { self.b } else { self.a }
}
pub fn get(&self) -> &B { unsafe { *self.c } }
pub fn get_mut(&mut self) -> &mut B { unsafe { *self.c } }
}
impl Drop for A {
fn drop(&mut self) {
unsafe {
Box::from_raw(self.a);
Box::from_raw(self.b);
}
}
}
我不会公开c
公开,因为它使用起来不安全。