介绍
视频地址:www.bilibili.com/video/av78062009/
相关源码:github.com/anonymousGiga/Rust-link...
详细内容
本节我们为链表实现Drop函数。按照我们常规的方式,我们可能的实现方式如下:
impl Drop for List { | |
fn drop(&mut self) {// NOTE: you can't actually explicitly call `drop` in real Rust code;// we're pretending to be the compiler! | |
self.head.drop(); // tail recursive - good!} | |
} | |
impl Drop for Link { | |
fn drop(&mut self) { | |
match *self { | |
Link::Empty => {} // Done! | |
Link::More(ref mut boxed_node) => { | |
boxed_node.drop(); // tail recursive - good!}}} | |
} | |
impl Drop for Box<Node> { | |
fn drop(&mut self) { | |
self.ptr.drop(); // uh oh, not tail recursive!deallocate(self.ptr);} | |
} | |
impl Drop for Node { | |
fn drop(&mut self) { | |
self.next.drop();} | |
} |
但是此种实现方式在编译时候会报错,因为Box中包含Node无法以递归的方式删除,因此,正确的实现方式如下:
impl Drop for List { | |
fn drop(&mut self) {let mut cur_link = mem::replace(&mut self.head, Link::Empty);while let Link::More(mut boxed_node) = cur_link { | |
cur_link = mem::replace(&mut boxed_node.next, Link::Empty);}} | |
} |
完整的代码如下:
use std::mem; | |
pub struct List{ | |
head: Link, | |
} | |
enum Link { | |
Empty,More(Box<Node>), | |
} | |
struct Node { | |
elem: i32, | |
next: Link, | |
} | |
impl List { | |
pub fn new() -> Self { | |
List { head: Link::Empty }} | |
pub fn push(&mut self, elem: i32) {let node = Box::new(Node { | |
elem: elem, | |
next: mem::replace(&mut self.head, Link::Empty),}); | |
self.head = Link::More(node);} | |
pub fn pop(&mut self) -> Option<i32> { | |
match mem::replace(&mut self.head, Link::Empty) { | |
Link::Empty => None, | |
Link::More(node) => { | |
self.head = node.next;Some(node.elem) | |
}}} | |
} | |
//impl Drop for List { | |
// fn drop(&mut self) { | |
// self.head.drop(); | |
// } | |
//} | |
// | |
//impl Drop for Link { | |
// fn drop(&mut self) { | |
// match *self { | |
// Link::Empty => {} // Done! | |
// Link::More(ref mut boxed_node) => { | |
// boxed_node.drop(); // tail recursive - good! | |
// } | |
// } | |
// } | |
//} | |
// | |
//impl Drop for Box<Node> { | |
// fn drop(&mut self) { | |
// self.ptr.drop(); // uh oh, not tail recursive! | |
// deallocate(self.ptr); | |
// } | |
//} | |
// | |
//impl Drop for Node { | |
// fn drop(&mut self) { | |
// self.next.drop(); | |
// } | |
//} | |
impl Drop for List { | |
fn drop(&mut self) {let mut cur_link = mem::replace(&mut self.head, Link::Empty);while let Link::More(mut boxed_node) = cur_link { | |
cur_link = mem::replace(&mut boxed_node.next, Link::Empty);}} | |
} | |
mod tests { | |
use super::List; | |
fn basics() {let mut list = List::new(); | |
assert_eq!(list.pop(), None); | |
list.push(1); | |
list.push(2); | |
list.push(3); | |
assert_eq!(list.pop(), Some(3)); | |
assert_eq!(list.pop(), Some(2)); | |
list.push(4); | |
list.push(5); | |
assert_eq!(list.pop(), Some(5)); | |
assert_eq!(list.pop(), Some(4)); | |
assert_eq!(list.pop(), Some(1)); | |
assert_eq!(list.pop(), None);} | |
} |