我正在尝试使用邻接列表创建一个图形,但我无法弄清楚如何为邻接列表中的引用指定适当的生命周期。
我想要了解的是:
struct Graph<T> {
nodes : Vec<T>,
adjacencies : Vec<Vec<&T>>
}
这不起作用,因为引用类型缺少生命周期说明符。我想我可以使用索引作为邻接,但我实际上对内部参考问题感兴趣,这只是表达这个问题的工具。
我看到它的方式,应该可以安全地进行,因为节点是由对象拥有的。应该允许它保持对那些节点的引用。
我是对的吗?怎么能在Rust做到这一点?或者,如果我错了,我错过了什么?
答案 0 :(得分:3)
由于Rust的内存安全性,在Rust中只能引用这个概念是不可能的 - 这样的对象如果没有已经存在就无法构建。只要nodes
和adjacencies
分开存储,就可以,但只要您尝试将它们连接到同一个结构中,就无法使其工作。
替代方法是使用引用计数(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
,尽管它是别名的。