如何在结构

时间:2016-03-13 16:41:05

标签: rust

这是一个定义结构的Rust伪代码片段:

struct A {
    a : *B;
    b : *B;
    pub c : *B;
}

(指针是C指针,不确定它们是否应该是Box或其他内容。)此处c始终设置为ab,所有访问都将通过c;为A定义的辅助方法将设置c = ac = 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()结尾处死亡,而不是在返回时逃脱)。

1 个答案:

答案 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公开,因为它使用起来不安全。