Drop
我们现在可以创建一个栈,推入元素,弹出元素,甚至确认了一切都可以正常的工作!
我们需要担心列表元素的清理么?严格的说,根本不用!就像C++,Rust使用析构器来自动的处理使用完毕的资源。如果一个类型实现了叫做 Drop 的特性(Trait),它就拥有一个析构器。特性是Rust对接口的特别术语。Drop特性有如下的接口:
基本上是这个意思:“当对象退出作用域的时候,我会给你清理事务的第二次机会”。
如果你的类型里存放有实现了Drop的其他类型,而你想要调用它们的析构器,是不需要实际实现Drop的。对于List来说,我们想做的不过是把列表头丢弃,之后或许会接着丢弃一个Box<Node>
。所有这些都会自动在一瞬间处理完成。
自动处理会很糟糕。
让我们考虑这个简单的列表。
当列表被丢弃时,它会先丢弃A,然后尝试丢弃B,然后会尝试丢弃C。现在你可能已经紧张起来了。这是递归代码,而递归代码会把栈爆掉!
有些人可能会想“这显然是尾部递归的,任何像样的语言都能确保这样的代码不会破坏堆栈”。事实上,这是不正确的!为了了解原因,让我们试着写下编译器必须做什么,像编译器那样手动实现列表的Drop:
我们不能在释放内存之后再丢弃Box的内容,所以没有办法以尾递归的形式进行 drop!作为替代,我们必须为List
手动编写一个迭代drop,来把节点从 box 中拿出来。
棒极了!
提前优化
我们的 drop 实际上非常类似于 while let Some (_) = self.pop(){} ,它当然更简单。一旦我们开始使用泛型存储整数以外的内容,它们之间有什么不同,以及可能会导致什么性能问题?
Last updated
Was this helpful?