6

编者注:此代码示例来自 Rust 1.0 之前的版本,在语法上不是有效的 Rust 1.0 代码。此代码的更新版本会产生不同的错误,但答案仍然包含有价值的信息。

我正在尝试在 Rust 中编写一个容器结构,其中的元素还存储对包含容器的引用,以便他们可以在其上调用方法。据我所知,我需要通过Rc<RefCell<T>>. 这个对吗?

到目前为止,我有以下内容:

struct Container {
  elems: ~[~Element]
}

impl Container {
  pub fn poke(&mut self) {
    println!("Got poked.");
  }
}

struct Element {
  datum: int,
  container: Weak<RefCell<Container>>
}

impl Element {
  pub fn poke_container(&mut self) {
    let c1 = self.container.upgrade().unwrap(); // Option<Rc>
    let mut c2 = c1.borrow().borrow_mut(); // &RefCell
    c2.get().poke();
//    self.container.upgrade().unwrap().borrow().borrow_mut().get().poke();
//    -> Error: Borrowed value does not live long enough * 2
  }
}

fn main() {
  let container = Rc::new(RefCell::new(Container{ elems: ~[] }));
  let mut elem1 = Element{ datum: 1, container: container.downgrade() };
  let mut elem2 = Element{ datum: 2, container: container.downgrade() };
  elem1.poke_container();
}

我觉得我在这里错过了一些东西。访问 a 的内容Rc<RefCell<T>>真的这么困难吗(in poke_container)?还是我以错误的方式解决问题?

最后,假设方法是正确的,我将如何编写一个add方法Container以便它可以填充container字段Element(假设我将字段更改为 type ?据我所知,Option<Rc<RefCell<T>>>我无法创建另一个Rc&mut self

4

1 回答 1

1

长长的方法调用链实际上对我来说在 master 上没有任何变化,因为“r-values”的生命周期(例如函数调用的结果)已经改变,因此临时返回值持续到语句结束,而不是而不是下一个方法调用的结束(这似乎是旧规则的工作方式)。

正如弗拉基米尔暗示的那样,可重载的取消引用可能会将其减少到

self.container.upgrade().unwrap().borrow_mut().poke();

哪个更好。

在任何情况下,在 Rust 中“变异”共享所有权总是(稍微)难于编写单一所有权代码或不可变共享所有权代码,因为这样的代码很容易成为内存不安全的(而内存安全是最重要的) Rust 的核心目标)。

于 2014-02-05T11:56:06.277 回答