匹配枚举时无法移出借用的内容
Cannot move out of borrowed content when matching an enum
我正在尝试打印一棵树(现在是 LinkedList
,但会修复):
use std::io;
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = *next;
}
NodeKind::Leaf => {
break;
}
}
}
let mut reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
编译器说:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:24:27
|
24 | current = *next;
| ^^^^^ cannot move out of borrowed content
我只读取值,没有更改任何内容。我正在从对另一个值的引用中分配一个值,试图取消对 Rc<T>
值的引用并将其存储在本地 mut
变量中。
也许这样的事情可能会奏效:
while true {
println!("{}", current.value);
match ¤t.kind {
&NodeKind::Branch(next) => {
current = next;
}
&NodeKind::Leaf => {
break;
}
}
}
或者也许
let mut current = &Rc::new(root);
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = &next;
}
NodeKind::Leaf => {
break;
}
}
}
但我得到了同样的错误加上 'next' does not live long enough
我还不能弄清楚 1) 的问题,但我确实找到了 2) 的答案。
在顶部,您需要使用:
use std::rc::Rc;
而不是
use std::rc;
显示错误是因为默认情况下 match
将执行移动。
移动值后(即未通过引用获取或调用采用 self
的方法)后续调用失败。您可能需要克隆,这是 属性 您的 struct
和 enum
所缺乏的。添加这些 (#[derive(Clone)
) 并将 current = *next;
更改为 current = (*next).clone();
后,您的程序将再次运行!
use std::io;
use std::rc::Rc;
#[derive(Clone)]
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
#[derive(Clone)]
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(std::rc::Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(std::rc::Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = (*next).clone();
}
NodeKind::Leaf => {
break;
}
}
}
let reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
如果你 let mut current = &root
那么你可以避免 clone()
按照下面 Vladimir 的回复 (playpen of Vladimir's version)。
这里不用clone,完全可以做你想实现的参考:
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = &root;
loop {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(ref next) => {
current = &**next;
}
NodeKind::Leaf => break,
}
}
}
您的代码唯一重要的变化是匹配中的模式是 ref next
并且 current
是 &Node
.
类型
ref
模式通过引用绑定它们的变量,即 next
具有类型 &Rc<Node>
。要从中获取 &Node
,您需要解引用它两次以获取 Node
,然后再次引用以获取 &Node
。由于 Deref 强制转换,也可以写成 current = &next
,编译器会自动为您插入适当数量的 *
。
我也从 while (true)
更改为 loop
,因为它更加地道并且有助于编译器推理您的代码。
所有树状结构的遍历在 Rust 中都是这样完成的。 ref
模式允许不移出变量,这在你只需要读取数据时是绝对必要的。您可以找到更多关于模式以及它们如何与所有权和借用交互的信息 here。
我正在尝试打印一棵树(现在是 LinkedList
,但会修复):
use std::io;
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = *next;
}
NodeKind::Leaf => {
break;
}
}
}
let mut reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
编译器说:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:24:27
|
24 | current = *next;
| ^^^^^ cannot move out of borrowed content
我只读取值,没有更改任何内容。我正在从对另一个值的引用中分配一个值,试图取消对 Rc<T>
值的引用并将其存储在本地 mut
变量中。
也许这样的事情可能会奏效:
while true {
println!("{}", current.value);
match ¤t.kind {
&NodeKind::Branch(next) => {
current = next;
}
&NodeKind::Leaf => {
break;
}
}
}
或者也许
let mut current = &Rc::new(root);
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = &next;
}
NodeKind::Leaf => {
break;
}
}
}
但我得到了同样的错误加上 'next' does not live long enough
我还不能弄清楚 1) 的问题,但我确实找到了 2) 的答案。
在顶部,您需要使用:
use std::rc::Rc;
而不是
use std::rc;
显示错误是因为默认情况下 match
将执行移动。
移动值后(即未通过引用获取或调用采用 self
的方法)后续调用失败。您可能需要克隆,这是 属性 您的 struct
和 enum
所缺乏的。添加这些 (#[derive(Clone)
) 并将 current = *next;
更改为 current = (*next).clone();
后,您的程序将再次运行!
use std::io;
use std::rc::Rc;
#[derive(Clone)]
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
#[derive(Clone)]
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(std::rc::Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(std::rc::Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = (*next).clone();
}
NodeKind::Leaf => {
break;
}
}
}
let reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
如果你 let mut current = &root
那么你可以避免 clone()
按照下面 Vladimir 的回复 (playpen of Vladimir's version)。
这里不用clone,完全可以做你想实现的参考:
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = &root;
loop {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(ref next) => {
current = &**next;
}
NodeKind::Leaf => break,
}
}
}
您的代码唯一重要的变化是匹配中的模式是 ref next
并且 current
是 &Node
.
ref
模式通过引用绑定它们的变量,即 next
具有类型 &Rc<Node>
。要从中获取 &Node
,您需要解引用它两次以获取 Node
,然后再次引用以获取 &Node
。由于 Deref 强制转换,也可以写成 current = &next
,编译器会自动为您插入适当数量的 *
。
我也从 while (true)
更改为 loop
,因为它更加地道并且有助于编译器推理您的代码。
所有树状结构的遍历在 Rust 中都是这样完成的。 ref
模式允许不移出变量,这在你只需要读取数据时是绝对必要的。您可以找到更多关于模式以及它们如何与所有权和借用交互的信息 here。