diff --git a/src/too-many-lists/unsafe-queue/layout2.md b/src/too-many-lists/unsafe-queue/layout2.md index 1931d368f3..227efa993c 100644 --- a/src/too-many-lists/unsafe-queue/layout2.md +++ b/src/too-many-lists/unsafe-queue/layout2.md @@ -37,6 +37,17 @@ struct Node { } ``` +细心的同学可能会发现,此时 `Link` 和 `tail` 的类型 `*mut Node` 一致了。我们可以把 `tail` 的类型也改为 `Link` ,让代码更一致。 + +```rust +pub struct List { + head: LinkT>, + // tail: *mut Node, + tail: Link, // 新老好人卡此时一致了 +} +``` + + 请大家牢记:当使用裸指针时,`Option` 对我们是相当不友好的,所以这里不再使用。在后面还将引入 `NonNull` 类型,但是现在还无需操心。 ## 基本操作 @@ -89,31 +100,31 @@ struct Node { > 将裸指针转换成 `Box` 以实现自动的清理: > > ```rust -> > let x = Box::new(String::from("Hello")); > let ptr = Box::into_raw(x); > let x = unsafe { Box::from_raw(ptr) }; 太棒了,简直为我们量身定制。而且它还很符合我们试图遵循的规则: 从安全的东东开始,将其转换成裸指针,最后再将裸指针转回安全的东东以实现安全的 drop。 -现在,我们就可以到处使用裸指针,也无需再注意 unsafe 的范围,反正现在都是 unsafe 了,无所谓。 +现在,我们就可以到处使用裸指针,只不过要注意 unsafe 的范围要尽可能小。大家可以再看下[之前的章节](https://course.rs/advance/unsafe/intro.html#控制-unsafe-的使用边界) 巩固巩固。 + ```rust pub fn push(&mut self, elem: T) { - unsafe { - // 一开始就将 Box 转换成裸指针 - let new_tail = Box::into_raw(Box::new(Node { - elem: elem, - next: ptr::null_mut(), - })); - - if !self.tail.is_null() { + // 一开始就将 Box 转换成裸指针 + let new_tail = Box::into_raw(Box::new(Node { + elem: elem, + next: ptr::null_mut(), + })); + + if !self.tail.is_null() { + unsafe { (*self.tail).next = new_tail; - } else { - self.head = new_tail; } - - self.tail = new_tail; + } else { + self.head = new_tail; } + + self.tail = new_tail; } ``` @@ -126,7 +137,10 @@ pub fn pop(&mut self) -> Option { if self.head.is_null() { None } else { - let head = Box::from_raw(self.head); + let head; + unsafe { + head = Box::from_raw(self.head); + } self.head = head.next; if self.head.is_null() {