在Rust中实现链表时如何复制原始指针?

在Rust中实现链表时如何复制原始指针?,rust,Rust,我正在Rust中编写递归类型ListNode。我必须在结构中使用框,我正在尝试编写一个循环来添加下一步列表节点。但是,我想尝试使用除递归方法之外的指针 #[derive(Debug)] struct ListNode { val: i32, next: Option<Box<ListNode>>, } impl ListNode { fn new(i: i32) -> Self { ListNode { val: i, ne

我正在Rust中编写递归类型
ListNode
。我必须在结构中使用
,我正在尝试编写一个循环来添加
下一步
列表节点
。但是,我想尝试使用除递归方法之外的指针

#[derive(Debug)]
struct ListNode {
    val: i32,
    next: Option<Box<ListNode>>,
}

impl ListNode {
    fn new(i: i32) -> Self {
        ListNode { val: i, next: None }
    }

    fn add_l(&mut self, l: &Vec<i32>) {
        let mut p: *mut ListNode = self as *mut ListNode;
        for i in l {
            unsafe {
                (*p).next = Some(Box::new(ListNode::new(*i)));
                let temp_b = Box::from_raw(p);
                p = Box::into_raw(temp_b.next.wrap());
            };
        }
    }
}

fn main() {
    let mut a = ListNode::new(1);
    a.add_l(&vec![2, 3, 4, 5]);
    println!("{:?}", a);
}
  • 有什么方法可以复制指针,使
    a
    保持稳定
  • 如果我无法复制指针,我如何实现它

  • 这里有许多问题,其中没有一个与复制指针有关

    我看到了您试图做的事情,但您看到的是“未定义的行为”,而不是复制指针值的失败

    首先,这是:

    temp_b.next.unwrap()
    
    “展开”不会将对象留在后面;它消耗它。通过的每次迭代,您将在调用
    展开时将
    next
    的值设置为nothing

    其次,在循环的第一次迭代中,将原始指针转换为一个方框:

    let mut p: *mut ListNode = self as *mut ListNode;
    // ... p is not reassigned before calling the next statement
    Box::from_raw(p);
    
    因此,当您使用temp_b时,您正在删除(释放)根对象a

    这不会立即触发崩溃,但这意味着您现在已经有效地破坏了堆栈。超过这一点的一切都是未定义的行为

    跟踪实际指针值时,请查看输出:

    #[derive(Debug)]
    struct ListNode {
        val: String,
        next: Option<Box<ListNode>>,
    }
    
    impl ListNode {
        fn new(i: &str) -> Self {
            ListNode { val: format!("{:?}", i), next: None }
        }
    
        fn add_l(&mut self, l: &Vec<&str>) {
            let mut p: *mut ListNode = self as *mut ListNode;
            println!("self -> {:?}", self as *mut ListNode);
            for i in l {
                unsafe {
                    (*p).next = Some(Box::new(ListNode::new(*i)));
                    let temp_b = Box::from_raw(p);
                    println!("{:?} -> {:?}", p, temp_b);
                    p = Box::into_raw(temp_b.next.unwrap());
                    println!("next p -> {:?}", p);
                };
    
            }
            println!("self -> {:?}", self as *mut ListNode);
        }
    }
    
    fn main() {
        let mut a = ListNode::new("1");
        a.add_l(&vec!["2", "3", "4", "5"]);
        println!("self -> {:?}", &mut a as *mut ListNode);
        println!("{:?}", a);
    }
    
    #[派生(调试)]
    结构列表节点{
    瓦尔:字符串,
    下一步:选择,
    }
    impl列表节点{
    fn新(i:&str)->Self{
    ListNode{val:format!(“{:?}”,i),下一个:无}
    }
    fn添加(多个自身,l:&Vec){
    让mut p:*mut ListNode=self作为*mut ListNode;
    println!(“self->{:?}”,self-as*mut-ListNode);
    因为我在l{
    不安全{
    (*p).next=Some(Box::new(ListNode::new(*i));
    设temp_b=Box::from_raw(p);
    println!(“{:?}->{:?}”,p,temp_b);
    p=Box::into_raw(temp_b.next.unwrap());
    println!(“下一个p->{:?}”,p);
    };
    }
    println!(“self->{:?}”,self-as*mut-ListNode);
    }
    }
    fn main(){
    让mut a=ListNode::new(“1”);
    a、 添加_l(&vec![“2”、“3”、“4”、“5”);
    println!(“self->{:?},&mut a as*mut ListNode);
    println!(“{:?}”,a);
    }
    

    self->0x7ffdc10a90f0
    0x7ffdc10a90f0->ListNode{val:“1\”,下一步:一些(ListNode{val:“2\”,下一步:无})
    下一个p->0x7fdde801f060
    0x7fdde801f060->ListNode{val:“2\”,下一步:一些(ListNode{val:“3\”,下一步:无})
    下一个p->0x7ffdc10a90f0
    0x7ffdc10a90f0->ListNode{val:“3\”,下一步:一些(ListNode{val:“4\”,下一步:无})
    下一个p->0x7fdde801f060
    0x7fdde801f060->ListNode{val:“4\”,下一步:一些(ListNode{val:“5\”,下一步:无})
    
    接下来p->0x7ffdc10a90f0这里有许多问题,其中没有一个与复制指针有关

    我看到了您试图做的事情,但您看到的是“未定义的行为”,而不是复制指针值的失败

    首先,这是:

    temp_b.next.unwrap()
    
    “展开”不会将对象留在后面;它消耗它。通过的每次迭代,您将在调用
    展开时将
    next
    的值设置为nothing

    其次,在循环的第一次迭代中,将原始指针转换为一个方框:

    let mut p: *mut ListNode = self as *mut ListNode;
    // ... p is not reassigned before calling the next statement
    Box::from_raw(p);
    
    因此,当您使用temp_b时,您正在删除(释放)根对象a

    这不会立即触发崩溃,但这意味着您现在已经有效地破坏了堆栈。超过这一点的一切都是未定义的行为

    跟踪实际指针值时,请查看输出:

    #[derive(Debug)]
    struct ListNode {
        val: String,
        next: Option<Box<ListNode>>,
    }
    
    impl ListNode {
        fn new(i: &str) -> Self {
            ListNode { val: format!("{:?}", i), next: None }
        }
    
        fn add_l(&mut self, l: &Vec<&str>) {
            let mut p: *mut ListNode = self as *mut ListNode;
            println!("self -> {:?}", self as *mut ListNode);
            for i in l {
                unsafe {
                    (*p).next = Some(Box::new(ListNode::new(*i)));
                    let temp_b = Box::from_raw(p);
                    println!("{:?} -> {:?}", p, temp_b);
                    p = Box::into_raw(temp_b.next.unwrap());
                    println!("next p -> {:?}", p);
                };
    
            }
            println!("self -> {:?}", self as *mut ListNode);
        }
    }
    
    fn main() {
        let mut a = ListNode::new("1");
        a.add_l(&vec!["2", "3", "4", "5"]);
        println!("self -> {:?}", &mut a as *mut ListNode);
        println!("{:?}", a);
    }
    
    #[派生(调试)]
    结构列表节点{
    瓦尔:字符串,
    下一步:选择,
    }
    impl列表节点{
    fn新(i:&str)->Self{
    ListNode{val:format!(“{:?}”,i),下一个:无}
    }
    fn添加(多个自身,l:&Vec){
    让mut p:*mut ListNode=self作为*mut ListNode;
    println!(“self->{:?}”,self-as*mut-ListNode);
    因为我在l{
    不安全{
    (*p).next=Some(Box::new(ListNode::new(*i));
    设temp_b=Box::from_raw(p);
    println!(“{:?}->{:?}”,p,temp_b);
    p=Box::into_raw(temp_b.next.unwrap());
    println!(“下一个p->{:?}”,p);
    };
    }
    println!(“self->{:?}”,self-as*mut-ListNode);
    }
    }
    fn main(){
    让mut a=ListNode::new(“1”);
    a、 添加_l(&vec![“2”、“3”、“4”、“5”);
    println!(“self->{:?},&mut a as*mut ListNode);
    println!(“{:?}”,a);
    }
    

    self->0x7ffdc10a90f0
    0x7ffdc10a90f0->ListNode{val:“1\”,下一步:一些(ListNode{val:“2\”,下一步:无})
    下一个p->0x7fdde801f060
    0x7fdde801f060->ListNode{val:“2\”,下一步:一些(ListNode{val:“3\”,下一步:无})
    下一个p->0x7ffdc10a90f0
    0x7ffdc10a90f0->ListNode{val:“3\”,下一步:一些(ListNode{val:“4\”,下一步:无})
    下一个p->0x7fdde801f060
    0x7fdde801f060->ListNode{val:“4\”,下一步:一些(ListNode{val:“5\”,下一步:无})
    
    接下来p->0x7ffdc10a90f0第一件事:使用
    不安全的
    这里是完全不必要的,如果我在任何真正的代码中看到它,我会说是主动恶意的。不要为了“好玩”而使用
    不安全的

    下面是该函数的一个完全安全的实现,它向后走以构造要添加的列表的新尾部:

    fn add_l(&mut self, l: &[i32]) {
        let mut tail = None;
    
        for &val in l.iter().rev() {
            let next = tail.take();
            tail = Some(Box::new(ListNode { val, next }));
        }
    
        self.next = tail;
    }
    
    和一个向前的,但需要一个
    展开的

    fn add_l(&mut self, l: &[i32]) {
        let mut head = self;
    
        for &val in l {
            head.next = Some(Box::new(ListNode::new(val)));
            head = { head }.next.as_mut().unwrap();
        }
    }
    
    如果您必须向前操作,并且必须避免
    展开
    ,那么您可能可以使用
    不安全
    。每个
    unsafe
    块都应该包含大量注释,解释代码是如何安全的,并且不会破坏您需要维护的保证

    fn add_l(&mut self, l: &[i32]) {
        let mut head = self;
    
        for &val in l {
            unsafe {
                // Boxing a value gives it a stable address.
                let mut node = Box::new(ListNode::new(val));
    
                // So long as this raw pointer doesn't escape this block, 
                // we don't need to worry about its lifetime as it should 
                // outlive what we need.
                let node_raw = &mut node as &mut ListNode as *mut ListNode;
    
                head.next = Some(node);
    
                // Now that we've moved the `Box` into its final place,
                // we throw away the reference to head to avoid mutable 
                // aliasing
                head = &mut *node_raw;
            }
        }
    }
    
    另见:


    第一件事:在这里使用
    不安全的
    是完全不必要的,如果我在任何真实的代码中看到它,我会说它是恶意的。