实际上,我尝试在 Rust 中实现以下功能。
我想要一个结构节点,它有一个指向其他节点结构的向量。此外,我有一个主向量,它保留所有已实例化的节点结构。
这里的关键点是节点是在循环内分配的(即自己的范围),并且保持所有结构(或对结构的引用)的主向量在循环外声明,在我看来这是一个 0815 用例。
经过大量尝试,我想出了仍然无法编译的代码。实际上我只用 &Node 和 RefCell<&Node> 尝试过,两者都不能编译。
struct Node<'a> {
name: String,
nodes: RefCell<Vec<&'a Node<'a>>>,
}
impl<'a> Node<'a> {
fn create(name: String) -> Node<'a> {
Node {
name: name,
nodes: RefCell::new(Vec::new()),
}
}
fn add(&self, value: &'a Node<'a>) {
self.nodes.borrow_mut().push(value);
}
fn get_nodes(&self) -> Vec<&'a Node> {
self.nodes.take()
}
}
// Later the code ...
let mut the_nodes_ref: HashMap<String, RefCell<&Node>> = HashMap::new();
let mut the_nodes_nodes: HashMap<String, &Node> = HashMap::new();
// This works
let no1_out = Node::create(String::from("no1"));
let no2_out = Node::create(String::from("no2"));
no1_out.add(&no2_out);
no2_out.add(&no1_out);
the_nodes_nodes.insert(no1_out.name.clone(), &no1_out);
the_nodes_nodes.insert(no2_out.name.clone(), &no2_out);
let no1_ref_out = RefCell::new(&no1_out);
let no2_ref_out = RefCell::new(&no2_out);
the_nodes_ref.insert(no1_out.name.clone(), no1_ref_out);
the_nodes_ref.insert(no2_out.name.clone(), no2_ref_out);
// This works not because no1 and no2 do not live long enough
let items = [1, 2, 3];
for _ in items {
let no1 = Node::create(String::from("no1"));
let no2 = Node::create(String::from("no2"));
no1.add(&no2); // <- Error no2 lives not long enough
no2.add(&no1); // <- Error no1 lives not long enough
the_nodes_nodes.insert(no1.name.clone(), &no1);
the_nodes_nodes.insert(no2.name.clone(), &no2);
let no1_ref = RefCell::new(&no1);
let no2_ref = RefCell::new(&no2);
the_nodes_ref.insert(no1.name.clone(), no1_ref);
the_nodes_ref.insert(no2.name.clone(), no2_ref);
}
我有点理解这个问题,但我想知道如何解决这个问题。如何在单独的范围内分配结构(此处为 for 循环),然后在 for 循环之外使用分配的结构。我的意思是在循环内分配结构并稍后在循环外使用它是一个常见的用例。
不知何故,我觉得缺少的链接是通过生命周期参数告诉 Rust 编译器,引用也应该在 for 循环之外保持活动状态,但我不知道该怎么做。但也许这也不是正确的方法......
实际上,这里的另一个关键点是我希望节点具有对其他节点的引用,而不是节点的副本。主向量也是如此,该向量应该具有对分配节点的引用,而不是节点的副本。