在Rust中实现链表时如何复制原始指针?
我正在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
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;
}
}
}
另见:
第一件事:在这里使用不安全的是完全不必要的,如果我在任何真实的代码中看到它,我会说它是恶意的。