简体   繁体   English

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

[英]How can I make a structure with internal references?

I'm trying to make a graph with adjacency lists, but I can't figure out how to specify an appropriate lifetime for the references in the adjacency list. 我正在尝试使用邻接列表创建一个图形,但我无法弄清楚如何为邻接列表中的引用指定适当的生命周期。

What I'm trying to get at is the following: 我想要得到的是以下内容:

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

This won't work because there is a lifetime specifier missing for the reference type. 这不起作用,因为引用类型缺少生命周期说明符。 I suppose I could use indices for the adjacencies, but I'm actually interested in the internal reference problem, and this is just a vehicle to express that problem. 我想我可以使用索引作为邻接,但我实际上对内部参考问题感兴趣,这只是表达这个问题的工具。

The way I see it, this should be possible to do safely, since the nodes are owned by the object. 我看到它的方式,应该可以安全地进行,因为节点是由对象拥有的。 It should be allowed to keep references to those nodes around. 应该允许它保持对这些节点的引用。

Am I right? 我对吗? How can this be done in Rust? 怎么能在Rust做到这一点? Or, if I'm wrong, what did I miss? 或者,如果我错了,我错过了什么?

It is not possible to represent this concept in Rust with just references due to Rust's memory safety—such an object could not be constructed without already existing. 由于Rust的内存安全性而无法在Rust中使用引用来表示此概念 - 这样的对象在没有已存在的情况下无法构建。 As long as nodes and adjacencies are stored separately, it's OK, but as soon as you try to join them inside the same structure, it can't be made to work thus. 只要nodesadjacencies是分开存储的,就可以了,但只要你尝试将它们连接在同一个结构中,它就无法工作。

The alternatives are using reference counting ( Rc<T> if immutable is OK or Rc<RefCell<T>> with inner mutability) or using unsafe pointers ( *const T or *mut T ). 替代方案是使用引用计数(如果不可变是Rc<T>或具有内部可变性的Rc<RefCell<T>> )或使用不安全指针( *const T*mut T )。

I think there is an issue here. 我认为这里有一个问题。 If we transpose this to C++: 如果我们将它转​​换为C ++:

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

where adjacencies points into nodes , then one realizes that there is an issue: an operation on nodes that invalidates references (such as reallocation) will leave dangling pointers into adjacencies . adjacencies点指向nodes ,然后人们意识到存在一个问题: nodes上的操作使引用无效(例如重新分配)会将悬空指针留给adjacencies

I see at least two ways to fix this: 我看到至少有两种方法可以解决这个问题:

  • Use indexes in adjacencies , as those are stable 使用adjacencies索引,因为它们是稳定的
  • Use a level of indirection in nodes , so that the memory is pinned nodes使用一个间接级别,以便固定内存

In Rust, this gives: 在Rust中,这给出了:

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

struct Graph<T> {
    nodes: Vec<Rc<RefCell<T>>>,
    adjacencies: Vec<Vec<Rc<RefCell<T>>>>,
};

Note: the RefCell is to allow mutating T despite it being aliased, by introducing a runtime check. 注意: RefCell允许通过引入运行时检查来改变T尽管它是别名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM