在 Rust 中实现链表时如何复制原始指针? [英] How to copy a raw pointer when implementing a linked list in Rust?
问题描述
我正在 Rust 中编写递归类型 ListNode
.我必须在结构中使用 Box
并且我正在尝试编写一个循环来添加 next
ListNode
.但是,我想尝试使用除递归方法之外的指针.
I am writing a recursive type ListNode
in Rust. I have to use Box
in the struct and I am trying to write a loop to add next
ListNode
. However, I would like to try using a pointer except recursive method.
#[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
被改成最后一个NodeList
,val
为5:
I found that a
is changed to the last NodeList
with the val
of 5:
ListNode { val: 5, next: None }
- 有什么方法可以复制一个指针来保持
a
的稳定? - 如果我无法复制指针,我该如何实现?
推荐答案
首先:使用 unsafe
在这里完全没有必要,如果我看到我会说是恶意的它在任何真正的代码中.不要用 unsafe
来好玩".
First things first: using unsafe
here is completely unnecessary and I would say actively malicious if I saw it in any real code. Don't use unsafe
for "fun".
这是一个完全安全的函数实现,它向后构建要添加的新列表尾部:
Here's a completely safe implementation of the function which walks backwards to construct the new tail of the list to add:
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;
}
还有一个继续前进,但需要一个unwrap
:
And one that goes forwards, but requires an unwrap
:
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
.每个 unsafe
块都应该包含大量注释,解释代码如何安全并且不会破坏您需要维护的保证.
If you had to do it in the forwards direction and had to avoid the unwrap
, then maybe you could use unsafe
. Every single unsafe
block should contain a wealth of comments explaining how the code is safe and doesn't break the guarantees that you need to uphold.
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;
}
}
}
另见:
这篇关于在 Rust 中实现链表时如何复制原始指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!