在获取递归数据结构的所有权时避免部分移动值?
Avoid partially moved value when taking ownership of a recursive data structure?
假设我有一个像单链表这样的递归数据结构,我想写一个递归函数在最后一个节点之后插入一个值*:
struct Node {
next: Option<Box<Node>>,
val: i32,
}
fn put_after_node(maybe_node: Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
None => Box::new(Node { next: None, val: val }),
Some(mut node) => {
// compile error on next line: use of partially moved value: `node`
node.next = Some(put_after_node(node.next, val));
node
}
}
}
问:如何避免编译错误抱怨 node
已被部分移动?
修复 #1 失败: 避免获取函数参数的所有权,取而代之的是 maybe_node: &mut Option<Box<Node>>
。失败,因为我需要添加一个新节点并将其传递回堆栈,如果我只有一个可变引用,那么我需要取消引用它,这会导致非法移出借用的值:
fn put_after_node(maybe_node: &mut Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
&mut None => Box::new(Node { next: None, val: val }),
&mut Some(ref mut node) => {
node.next = Some(put_after_node(&mut node.next, val));
*node // compile error: cannot move out of borrowed content
}
}
}
修复 #2 失败: Return 改为引用新节点 (fn ... -> &Box<Node>
)。失败,因为新节点的寿命不够长(或者至少,我无法弄清楚如何指定新节点的寿命,以便它的寿命至少与返回的对它的引用一样长)来自函数)。
fn put_after_node(maybe_node: &mut Option<Box<Node>>, val: i32) -> &Box<Node> {
match maybe_node {
// compile error on next line: borrowed value does not live long enough
&mut None => &Box::new(Node { next: None, val: val }),
&mut Some(ref mut node) => {
// compile error on next line: cannot move out of borrowed content
node.next = Some(*put_after_node(&mut node.next, val));
node
}
}
}
(* 原始片段是我尝试对 this red black tree implementation 的 put()
进行的 Rust 音译的简化版本。我意识到我在这里概述的最小示例作为一个循环会更好,但我实际尝试编写的代码并非如此。)
更新: 我不认为这是 的重复,因为 a) 我正在尝试处理不同的错误消息 & b) 我的fn
需要 self
- 而不是 &mut self
。话虽如此,我可能会尝试将其重写为 &mut self
,所以感谢指点@shepmaster。
使用 take()
获取期权的价值(它本身在幕后使用 mem::replace()
):
fn put_after_node(maybe_node: Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
None => Box::new(Node { next: None, val: val }),
Some(mut node) => {
// note the node.next.take()
node.next = Some(put_after_node(node.next.take(), val));
node
}
}
}
假设我有一个像单链表这样的递归数据结构,我想写一个递归函数在最后一个节点之后插入一个值*:
struct Node {
next: Option<Box<Node>>,
val: i32,
}
fn put_after_node(maybe_node: Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
None => Box::new(Node { next: None, val: val }),
Some(mut node) => {
// compile error on next line: use of partially moved value: `node`
node.next = Some(put_after_node(node.next, val));
node
}
}
}
问:如何避免编译错误抱怨 node
已被部分移动?
修复 #1 失败: 避免获取函数参数的所有权,取而代之的是 maybe_node: &mut Option<Box<Node>>
。失败,因为我需要添加一个新节点并将其传递回堆栈,如果我只有一个可变引用,那么我需要取消引用它,这会导致非法移出借用的值:
fn put_after_node(maybe_node: &mut Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
&mut None => Box::new(Node { next: None, val: val }),
&mut Some(ref mut node) => {
node.next = Some(put_after_node(&mut node.next, val));
*node // compile error: cannot move out of borrowed content
}
}
}
修复 #2 失败: Return 改为引用新节点 (fn ... -> &Box<Node>
)。失败,因为新节点的寿命不够长(或者至少,我无法弄清楚如何指定新节点的寿命,以便它的寿命至少与返回的对它的引用一样长)来自函数)。
fn put_after_node(maybe_node: &mut Option<Box<Node>>, val: i32) -> &Box<Node> {
match maybe_node {
// compile error on next line: borrowed value does not live long enough
&mut None => &Box::new(Node { next: None, val: val }),
&mut Some(ref mut node) => {
// compile error on next line: cannot move out of borrowed content
node.next = Some(*put_after_node(&mut node.next, val));
node
}
}
}
(* 原始片段是我尝试对 this red black tree implementation 的 put()
进行的 Rust 音译的简化版本。我意识到我在这里概述的最小示例作为一个循环会更好,但我实际尝试编写的代码并非如此。)
更新: 我不认为这是 fn
需要 self
- 而不是 &mut self
。话虽如此,我可能会尝试将其重写为 &mut self
,所以感谢指点@shepmaster。
使用 take()
获取期权的价值(它本身在幕后使用 mem::replace()
):
fn put_after_node(maybe_node: Option<Box<Node>>, val: i32) -> Box<Node> {
match maybe_node {
None => Box::new(Node { next: None, val: val }),
Some(mut node) => {
// note the node.next.take()
node.next = Some(put_after_node(node.next.take(), val));
node
}
}
}