【问题标题】:Rust data moved E0507 but I can't get the references workingRust 数据移动了 E0507,但我无法让参考工作
【发布时间】:2022-01-20 10:15:21
【问题描述】:

我对 Rust 非常陌生,对于一项任务,我必须实现一个名为“SortedContainer”的二叉树。我遇到的问题是数据以某种方式移动,我似乎无法让引用工作。

错误代码是E0507。它出现在 Sortedcontainer 实现的插入函数中的“match self.root”中。

Rust 建议 &self 但这会产生类型错误:他希望在 BTNode::insert(foundNode, age, name) 中找到一个 Box,但找到了一个引用。 foundNode 现在是错误。试图解除它不起作用(*foundNode)。这样做的原因是“发生移动是因为 *foundNode 的类型 Box<BTNode<i32, String>> 没有实现 Copy 特征。

这是我的代码:

type ChildNode<T,U> = Option<Box<BTNode<T,U>>>; //Define alias (type); prevents recursive type (= self-reference), points to heap (box). Optional (option)

pub struct BTNode<T,U>{
    left: ChildNode<T,U>, //Box prevents recursive type/self-reference; points to object on the heap
    right: ChildNode<T,U>,
    age: T,
    name: U
}

impl BTNode<i32, String>{
    pub fn new(l: ChildNode<i32, String>, r: ChildNode<i32, String>, a: i32, n: String) -> Self{ //ChildNode very important, otherwise no unit. values allowed.
        BTNode::<i32,String>{
            left: l, right: r, age: a, name: n
        }
    }
    pub fn insert(mut node: Box<BTNode<i32, String>>, age: i32, name: String) -> Box<BTNode<i32, String>>{
        if age < node.age {
            match node.left {
                None => node.left = Some(Box::new(BTNode::new(None, None, age, name))),
                Some(foundNode) => return BTNode::insert(foundNode, age, name),
            }
        } else if age > node.age { //This else keeps the "name" from going out of scope
            match node.right {
                None => node.right = Some(Box::new(BTNode::new(None, None, age, name))),
                Some(foundNode) => return BTNode::insert(foundNode, age, name),
            }
        }
        eprintln!("Undefined/Unimplemented behaviour: age already present in tree. Failed to insert into tree");
        std::process::exit(0x0100); //Error code 0 on linux, 256 on Windows
    }
}

pub struct SortedContainer<T,U>{
    root: ChildNode<T,U>
}

impl SortedContainer <i32,String> { //Tree
    pub fn new() -> Self{
        SortedContainer::<i32,String>{
            root: None,
        }
    }
    pub fn insert(&mut self, age: i32, name: String) { //self is a keyword; self      cannot be replaced by say "tree";
        match self.root {     //ERROR E0507 HERE. If &self, then error below
            None => {
                self.root = Some(Box::new(BTNode::new(None, None, age, name)));
            },
            Some(foundNode) => {
                BTNode::insert(foundNode, age, name); //If &self, then foundNode has error E0308 mismatched types. Expected struct Box, found reference.
                           //If dereferenced, then error E0507 again.    
            }
        }
    }
}

编辑:这可能是一些相关信息。这就是我尝试使用 SortedContainer 以及测试它的方式。

fn main() {
    let mut tree: tree::SortedContainer<i32, String> = tree::SortedContainer::new();
    tree.insert(32, "Papa Johns".to_string()); //This works due to the self parameter in the function 
    tree.insert(24, "Johan".to_string());
    tree.insert(8, "EvaBeva".to_string());
    tree.insert(64, "PizzaLoverYesYes".to_string());
    tree.print();
}

【问题讨论】:

  • 在您的代码中注释掉 pub fn print(&amp;self) {} 不会改变错误 - play.rust-lang.org/…。您确定您没有更改任何其他内容吗?
  • 请记住,二叉树基本上是一组具有一些共同元素的链表,您应该阅读:Learn Rust With Entirely Too Many Linked Lists
  • @Cerberus 你是对的,它消除了 Visual Studio Code 指示的所有错误,但它仍然给出编译器错误。然而,错误又是 E0507。它也出现在同一行,即来自 SortedContainer 实现中的插入函数的“匹配 self.root”。我正在编辑问题
  • None 分支在您的insert 函数中分配给一个字段但不返回值,因此执行将脱离if-else 链并运行到您的流程结束逻辑。 (PS 改用panic!("age already present in tree");

标签: rust move


【解决方案1】:

当您在SortedContainer::insert 中解构self.root 并从其中取出foundNode 时,有3 个选项:

  1. 要么按值取值(这是默认设置,也称为“移动”)
  2. 或者您制作一个副本(“克隆”)
  3. 或者你参考一下

情况1不是你想要的,因为它会将foundNode与self.root分开,并使其无效,但你想在调用insert之后再次继续使用self.root。

情况 2 可能不是您想要的,因为复制整个子树的性能不是很好。

所以最好传递一个参考。在这种情况下,您还需要调整 BTNode::insert 以接受引用(当前在您的版本中它需要一个值):

pub fn insert(node: &mut Box<BTNode<i32, String>>, ...

【讨论】:

  • 这是正确的方向,但 OP 必须改变的不仅仅是函数签名才能使其工作。最好解决所有必需的修复。
  • 这并不是我一直在寻找的答案,但它确实帮助我更好地理解 Rust。谢谢你。我自己尝试了一些事情,我的任务伙伴找到了解决其中一个试验/实施的方法。我在“None =>”中有“self.root = ...”,但在“Some(...)”中没有“self.root = ...”。毕竟这是一个逻辑问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 2021-11-01
  • 1970-01-01
  • 2017-10-15
  • 2012-07-22
  • 2014-05-24
相关资源
最近更新 更多