In the below code, I clone the head of an already existing linked list.
I change the value of the next node using the cloned head. Why is the original list unchanged.
I assume since next here is a pointer, changing next should affect current clone as well as original. Both the cloned head and original head should be pointing to the same next no ??
#[derive(Debug, Clone)]
pub struct List {
pub head: Option<Box<ListNode>>
}
#[derive(Debug, Clone)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
fn main() {
let mut list = List::new();
list.push(5);
list.push(4);
list.push(3);
list.push(2);
list.push(1);
list.push(0);
let mut clist = list.clone();
// modified first node
clist.head.as_mut().unwrap().val = 111;
// modified second node
clist.head.as_mut().unwrap().next.as_mut().unwrap().val = 123;
println!("{:?}", list);
}
Well, ListNode contains next as Box<Option<ListNode>>, therefore to clone node you have to clone node.next. And cloning the Box clones its contents, so you have to clone the ListNode stored in next, if any. Therefore, in this case the whole list will be cloned, too.
That's the nature of Box. It's owning pointer and there can not be any other owner.
If you would use Rc instead of Box then only head would be cloned. Because Rc is designed for that. With Rc you can have two owning pointers to the same node.
It's just an address but it's unique owning pointer. That's the semantic of Box. It's analogue of std::unique_ptr in C++.
Arc is analogue of std::shared_ptr which means it can do what you expect. And Rc is single-thread shared_ptr (C++ doesn't have anything like that because it's too dangerous in C++) thus it can do, too.
But it's forbidden for two Box'es to share the content which means clone have no choice. If it's implemented at all (and it's implemented) then it has to clone content.