如何使用内部引用构建结构?

时间:2014-11-18 18:12:02

标签: rust

我正在尝试使用邻接列表创建一个图形,但我无法弄清楚如何为邻接列表中的引用指定适当的生命周期。

我想要了解的是:

struct Graph<T> {
    nodes : Vec<T>,
    adjacencies : Vec<Vec<&T>>
}

这不起作用,因为引用类型缺少生命周期说明符。我想我可以使用索引作为邻接,但我实际上对内部参考问题感兴趣,这只是表达这个问题的工具。

我看到它的方式,应该可以安全地进行,因为节点是由对象拥有的。应该允许它保持对那些节点的引用。

我是对的吗?怎么能在Rust做到这一点?或者,如果我错了,我错过了什么?

2 个答案:

答案 0 :(得分:3)

由于Rust的内存安全性,在Rust中只能引用这个概念是不可能的 - 这样的对象如果没有已经存在就无法构建。只要nodesadjacencies分开存储,就可以,但只要您尝试将它们连接到同一个结构中,就无法使其工作。

替代方法是使用引用计数(Rc<T>如果不可变或Rc<RefCell<T>>具有内部可变性)或使用不安全指针(*const T*mut T)。

答案 1 :(得分:2)

我认为这里有一个问题。如果我们将它转​​换为C ++:

template <typename T>
struct Graph {
    std::vector<T> nodes;
    std::vector<std::vector<T*>> adjacencies;
};

其中adjacencies指向nodes,然后人们意识到存在问题:nodes上的操作使引用无效(例如重新分配)会将悬空指针留给{{1 }}

我发现至少有两种方法可以解决这个问题:

  • 使用adjacencies中的索引,因为它们是稳定的
  • adjacencies中使用间接级别,以便固定内存

在Rust中,这给出了:

nodes

注意:struct Graph<T> { nodes: Vec<T>, adjacencies: Vec<Vec<uint>>, }; struct Graph<T> { nodes: Vec<Rc<RefCell<T>>>, adjacencies: Vec<Vec<Rc<RefCell<T>>>>, }; 允许通过引入运行时检查来变异RefCell,尽管它是别名的。