匹配枚举时无法移出借来的内容

Ale*_*kiy 6 enums rust

我正在尝试打印出一棵树(它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);
}
Run Code Online (Sandbox Code Playgroud)

编译器说:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:24:27
   |
24 |                 current = *next;
   |                           ^^^^^ cannot move out of borrowed content
Run Code Online (Sandbox Code Playgroud)

我只阅读价值,而不是改变任何东西.我将引用中的Rc<T>mut赋给另一个值,尝试取消引用值并将其存储在局部变量中.

也许这样的事可能有用:

while true {
    println!("{}", current.value);
    match &current.kind {
        &NodeKind::Branch(next) => {
            current = next;
        }
        &NodeKind::Leaf => {
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或者可能

let mut current = &Rc::new(root);
while true {
    println!("{}", current.value);
    match current.kind {
        NodeKind::Branch(next) => {
            current = &next;
        }
        NodeKind::Leaf => {
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但我得到同样的错误加 'next' does not live long enough

Vla*_*eev 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,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

代码中唯一重要的变化是匹配中的模式是ref nextcurrent类型&Node.

ref模式通过引用绑定它们的变量,即next具有类型&Rc<Node>.为了得到&Node它,你需要取消引用它两次得到Node,然后再次引用得到&Node.由于Deref强制,也可以编写current = &next,编译器将*自动为您插入适当数量的s.

我也改变了while (true),loop因为它更惯用,它有助于编译器推理你的代码.

在Rust中,树状结构的所有遍历都是这样完成的.ref模式允许不移出变量,这在您只需要读取数据时是绝对必要的.您可以在此处找到有关模式以及它们如何与所有权和借用交互的更多信息.