我试图打印出一棵树(它现在是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
答案 0 :(得分:8)
这里没有必要克隆,绝对可以通过引用来实现你想要的目标:
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进行交互的更多信息。
答案 1 :(得分:3)
显示错误,因为默认情况下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
,那么您可以根据弗拉基米尔的回复(playpen of Vladimir's version)来避免clone()
。
答案 2 :(得分:1)
我无法弄清楚1)的问题,但我找到了2)的答案。
在顶部,您需要使用:
use std::rc::Rc;
而不是
use std::rc;