我对Rust很感兴趣,现在我开始用这种语言开展我的第一个非平凡的项目。我仍然在完全理解借贷和终身概念方面遇到一些麻烦。
该应用程序是一个逻辑门模拟器,其中组件是递归定义的(就其他组件及其互连而言)。
我目前的计划是通过让Component组件拥有一个Components(它的子组件)的向量和一个描述这些组件之间的内部连接的Nets向量来实现这个,就像在C ++中一样:
pub struct Pin {
name: String
}
pub struct Net<'a> {
nodes: Vec<(&'a Component<'a>,&'a Pin)>
}
pub struct Component<'a> {
sub_components: Vec<Box<Component<'a>>>,
in_pins: Vec<Pin>,
out_pins: Vec<Pin>,
netlist: Vec<Net<'a>>
}
impl<'a> Component<'a> {
pub fn new() -> Component<'a> {
...
}
pub fn add_subcomponent( & mut self, comp: Component<'a> ) {
// -> &Box<Component<'a>> ??
....
}
}
在C ++中,Net很容易实现为指向组件的指针数组,但我不确定在Rust中执行此操作的最佳方法,我想我应该使用借来的指针?或者有更好的方法吗?
考虑以下主要内容:
fn main() {
let sub1 = Component::new();
let sub2 = Component::new();
let circuit = Component::new();
circuit.add_subcomponent( sub1 );
circuit.add_subcomponent( sub2 );
// sub1 and sub2 are now empty...
}
如何配置电路以在sub1和sub2之间创建网络?我有add_subcomponent返回一个借用指向添加的组件的指针吗?还是盒子?
如果有人能指出我正确的方向,那就太好了。
非常感谢。
答案 0 :(得分:8)
您不能代表安全生锈中的任意图形结构。
实现此模式的最佳方法是使用不安全的代码和原始指针,或者将此功能包装在安全API中的现有抽象,例如http://static.rust-lang.org/doc/master/std/cell/struct.RefCell.html
例如,典型的双向链表是:
struct Node {
next: Option<Node>, // Each node 'owns' the next one
prev: *mut Node // Backrefs are unsafe
}
有很多“安全”的实现,你有类似的东西:
struct Node {
id: u32,
next: u32,
prev: u32
}
struct Nodes {
all:Vec<Node>,
root:Option<Node>
}
这在技术上是'安全',但这是一种可怕的模式;它通过手动实现原始指针来打破所有安全规则。我强烈建议不要这样做。
您可以尝试使用引用,例如:
struct Container<'a> {
edges:Vec<Edge<'a>>,
pub root: Node
}
struct Node {
children:Vec<Node>
}
struct Edge<'a> {
n1: &'a Node,
n2: &'a Node
}
......但是你几乎会立刻绊倒到借用检查器的地狱。例如,当您删除节点时,借用检查器如何知道“边缘”中的关联链接不再有效?
虽然你可能能够定义结构,但填充它们会非常麻烦。
我知道这可能是一个非常不满意的答案;你可能会发现搜索github的'rust graph'和'rust tree'很有用,看看其他人做过的实现。
通常,它们会将子树的单一所有权强制实施为父对象。