我已经查看了很多主题,但是我找不到任何关于为什么我的代码无法编译的线索(除了当然的所有权问题),希望有人在这里可以帮助我。
我正在开发二叉树实现,其中一个函数是 insert 函数。这是我第一次在Rust编写代码,虽然我已多次查看文档,但我无法弄清楚以下代码中的所有权有什么问题(我只发布了,希望所有相关代码):
#[derive(Debug)]
struct Data {
name: String,
age: i32,
}
#[derive(Debug)]
struct Node {
value: Data,
left: Option<Box<Node>>,
right: Option<Box<Node>>,
}
pub struct SortedContainer {
root: Option<Box<Node>>,
}
impl SortedContainer {
pub fn insert(&mut self, name: String, age: i32) {
let d = Data {
name: name,
age: age,
};
let n = Node {
value: d,
left: None,
right: None,
};
match self.root {
Some(ref rootnode) => SortedContainer::node_insert(n, *rootnode),
None => self.root = Some(Box::new(n)),
}
}
fn node_insert(n: Node, mut n2: Box<Node>) {
let i = SortedContainer::data_compare(&n.value, &n2.value);
if i < 0 {
match n2.right {
Some(ref rightnode) => SortedContainer::node_insert(n, *rightnode),
None => n2.right = Some(Box::new(n)),
}
} else if i > 0 {
match n2.left {
Some(ref leftnode) => SortedContainer::node_insert(n, *leftnode),
None => n2.left = Some(Box::new(n)),
}
}
}
fn data_compare(d: &Data, d2: &Data) -> i32 {
if d.age < d2.age {
return -1;
} else if d.age > d2.age {
return 1;
} else if d.name == d2.name {
return 0;
} else if d.name > d2.name {
return 1;
} else if d.name < d2.name {
return -1;
} else {
return 0;
}
}
}
终端提供的错误是:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:31:67
|
31 | Some(ref rootnode) => SortedContainer::node_insert(n, *rootnode),
| ^^^^^^^^^ cannot move out of borrowed content
error[E0507]: cannot move out of borrowed content
--> src/main.rs:39:72
|
39 | Some(ref rightnode) => SortedContainer::node_insert(n, *rightnode),
| ^^^^^^^^^^ cannot move out of borrowed content
error[E0507]: cannot move out of borrowed content
--> src/main.rs:44:71
|
44 | Some(ref leftnode) => SortedContainer::node_insert(n, *leftnode),
| ^^^^^^^^^ cannot move out of borrowed content
它是否与Box
或左/右分配有关?
答案 0 :(得分:2)
您正试图将您的盒装节点移出其封闭选项。这是不允许的,因为之后选项仍将由相应的父节点拥有。理论上,您可以在选项上调用take
来移动节点。 take
将值移出选项并将其替换为None
,而不是将其替换为#34;为空&#34; (不允许)。
但是,这将有效地将子节点与其各自的父节点分离。从插入新节点返回后,您必须重新附加它们:
fn node_insert(n: Node, mut n2: Box<Node>) -> Box<Node>{
let i = SortedContainer::data_compare(&n.value, &n2.value);
if i < 0 {
n2.right = match n2.right.take() {
Some(rightnode) => Some(SortedContainer::node_insert(n, rightnode)),
None => Some(Box::new(n)),
}
} else if i > 0 {
n2.left = match n2.left.take() {
Some(leftnode) => Some(SortedContainer::node_insert(n, leftnode)),
None => Some(Box::new(n)),
}
}
n2
}
根节点相同:
self.root = match self.root.take() {
Some(rootnode) => Some(SortedContainer::node_insert(n, rootnode)),
None => Some(Box::new(n)),
}
另一种解决方案涉及将可变引用传递给节点而不是移动它们。这是有效的,因为您实际上只需要沿着从根节点到应该插入新节点的叶节点的路径改变节点:
fn node_insert(n: Node, n2: &mut Node) {
let i = SortedContainer::data_compare(&n.value, &n2.value);
if i < 0 {
match n2.right {
Some(ref mut rightnode) => SortedContainer::node_insert(n, rightnode),
None => n2.right = Some(Box::new(n)),
}
} else if i > 0 {
match n2.left {
Some(ref mut leftnode) => SortedContainer::node_insert(n, leftnode),
None => n2.left = Some(Box::new(n)),
}
}
}
根节点相同:
match self.root {
Some(ref mut rootnode) => SortedContainer::node_insert(n, rootnode),
None => self.root = Some(Box::new(n)),
}