Struct 调用采用“self”的方法时,不会修改数据结构`

Struct 调用采用“self”的方法时,不会修改数据结构`,struct,rust,Struct,Rust,我正在写一个二叉树结构,我在insert函数中遇到了问题。调用函数在我的节点中插入数据后,该节点不会被修改 use std::ptr; #[derive(Clone, Copy)] struct Node<T> { data: Option<T>, left: *mut Node<T>, right: *mut Node<T>, } impl<T> Node<T> { pub fn new

我正在写一个二叉树结构,我在
insert
函数中遇到了问题。调用函数在我的节点中插入数据后,该节点不会被修改

use std::ptr;

#[derive(Clone, Copy)]
struct Node<T> {
    data: Option<T>,
    left: *mut Node<T>,
    right: *mut Node<T>,
}

impl<T> Node<T> {
    pub fn new(data: T) -> Node<T> {
        Node {
            data: Some(data),
            left: ptr::null_mut(),
            right: ptr::null_mut(),
        }
    }

    pub fn insert(mut self, data: T) {
        let tmp = self.data.unwrap();
        self.data = None;

        self.left = &mut Node::new(data);
        self.right = &mut Node::new(tmp);
    }
}

impl<T: std::fmt::Display> std::fmt::Display for Node<T>
    where T: std::fmt::Debug
{
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self.data {
            Some(ref x) => {
                write!(f, "Node data: {}, left: {}, right: {}", x, 
                        if self.left.is_null() {"null"} else {"not null"}, 
                        if self.right.is_null() {"null"} else {"not null"}, 
                    )
            }
            None => {
                write!(f, "Node data: None, left: {}, right: {}",  
                        if self.left.is_null() {"null"} else {"not null"}, 
                        if self.right.is_null() {"null"} else {"not null"}, 
                    )
            }
        }
    }
}

fn main() {
    let mut root: Node<i32> = Node::new(32);
    println!("Root before insert : {}", root);
    root.insert(42);
    println!("Root after insert: {}", root);
}

我的节点在函数插入后未被修改。我能做些什么来解决这个问题?

既然您看起来很困惑,让我们开始吧

首先,没有理由使用原始指针。此外,我建议不要使用
Copy
,因为它只会隐藏所有权问题。最后,派生
调试
要比手动实现格式化容易得多(并且它允许以更自动化的方式试验结构的布局)

没有什么悬而未决的问题,让我们转到
insert

impl<T> Node<T> {
    fn insert(&mut self, data: T) {
        let current = self.data.take().expect("Cannot insert in empty node!");

        self.left = Some(Box::new(Node::new(current)));
        self.right = Some(Box::new(Node::new(data)));
    }
}

还有

既然你看起来很困惑,让我们开始吧

首先,没有理由使用原始指针。此外,我建议不要使用
Copy
,因为它只会隐藏所有权问题。最后,派生
调试
要比手动实现格式化容易得多(并且它允许以更自动化的方式试验结构的布局)

没有什么悬而未决的问题,让我们转到
insert

impl<T> Node<T> {
    fn insert(&mut self, data: T) {
        let current = self.data.take().expect("Cannot insert in empty node!");

        self.left = Some(Box::new(Node::new(current)));
        self.right = Some(Box::new(Node::new(data)));
    }
}

还有

您是指
&mut self
,因为您是按值获取节点的。。。(如果您的
节点
不是
副本
,您会注意到这一点)。@MatthieuM。当我试图将
self.data.unwrap()
中的值复制到
tmp
中时,使用
&mut self
会导致有关借用内容的错误,这是一个单独的问题;使用
&mut self
是修改方法受体的唯一方法。另一种解决方案是使用
mut self
并返回
Node
,然后将调用站点更改为
root=root.insert(…)。我们可以帮助解决任何一种情况,所以只需选择您喜欢的任何一种。我知道返回
Node
是解决问题的一种方法,但我想知道是否有一种方法可以更好地执行OOP-like@MatthieuM. 这将是一个难以回答的问题。请注意,OP通过
self.left=&mut Node::new(data)
为内存安全埋下了一颗巨大的地雷。一旦这些值被取消引用。。。。Boooom.你是说
&mut self
,因为你是按值获取节点的。。。(如果您的
节点
不是
副本
,您会注意到这一点)。@MatthieuM。当我试图将
self.data.unwrap()
中的值复制到
tmp
中时,使用
&mut self
会导致有关借用内容的错误,这是一个单独的问题;使用
&mut self
是修改方法受体的唯一方法。另一种解决方案是使用
mut self
并返回
Node
,然后将调用站点更改为
root=root.insert(…)。我们可以帮助解决任何一种情况,所以只需选择您喜欢的任何一种。我知道返回
Node
是解决问题的一种方法,但我想知道是否有一种方法可以更好地执行OOP-like@MatthieuM. 这将是一个难以回答的问题。请注意,OP通过
self.left=&mut Node::new(data)
为内存安全埋下了一颗巨大的地雷。一旦这些值被取消引用。。。。Boooom.是的,我确信
数据
需要作为插入选项。否则,您知道为什么它与
Box
一起工作而不与原始指针一起工作吗?谢谢你的回答,我修改了你的代码,做了我想做的事情,很有魅力,谢谢@Bl4ckb0ne:将
None
分配给
self.data
take
之后是不必要的<代码>获取
已获取
选项的内容
并将其替换为
。至于原始指针:您无意中创建了一个指向堆栈上某个变量的指针,当您尝试取消引用它时,该指针会崩溃。原始指针功能强大且不安全(取消引用它们需要
unsafe
关键字)<代码>框
会将内容放在堆上,并为您管理生存期。是的,我确信
数据
需要作为插入选项。否则,您知道为什么它与
Box
一起工作而不与原始指针一起工作吗?谢谢你的回答,我修改了你的代码,做了我想做的事情,很有魅力,谢谢@Bl4ckb0ne:将
None
分配给
self.data
take
之后是不必要的<代码>获取
已获取
选项的内容
并将其替换为
。至于原始指针:您无意中创建了一个指向堆栈上某个变量的指针,当您尝试取消引用它时,该指针会崩溃。原始指针功能强大且不安全(取消引用它们需要
unsafe
关键字)<代码>框
将把内容放在堆上,并为您管理生存期。
impl<T> Node<T> {
    fn insert(&mut self, data: T) {
        let current = self.data.take().expect("Cannot insert in empty node!");

        self.left = Some(Box::new(Node::new(current)));
        self.right = Some(Box::new(Node::new(data)));
    }
}
fn main() {
    let mut root: Node<i32> = Node::new(32);
    println!("Root before insert : {:?}", root);
    root.insert(42);
    println!("Root after insert: {:?}", root);
}