请注意,这个问题指的是Rust 1.0之前的Rust版本。尽管语法已经更改,但概念仍然有效。
你可以很容易地使用拥有的指针实现一个只转发的链表,比如:
struct Node<T> {
next: Option<~Node<T>>,
data: T
}
想象一下,如果你想高效地实现一个支持四个基本操作的队列:
push
:添加到列表末尾pop
:从列表末尾删除并返回unshift
:添加到列表的前面shift
:从列表末尾删除并返回
在使用普通指针的语言中,您可以使用双向链表和根对象来实现这一点,根对象存储指向列表中第一个和最后一个元素的first
和last
指针。
我看不出你会如何在Rust中实现这一点。
我可以隐约猜到你会使用一堆引用,也许是这样的:
struct Node<T> {
next: Option<&Node<T>>,
prev: Option<&Node<T>>,
data: T
}
...但是我不知道你如何管理这些变量的生存期范围。
谁能给我指出这个方向,或者一个类似的例子,涉及对象之间引用的复杂生命周期?
(这种代码风格的另一个典型示例是观察者模式,其中许多对象必须将事件更新发布到单个位置,例如UINode
〈〉----EventObserver
〈〉----EventCore
〈〉----UINodes
;复杂层次结构中的多个对象共享指针,其中事件从叶节点向下传播到某个核心,然后被推出到不同的叶节点)
3条答案
按热度按时间n6lpvg4x1#
我建议您看一看Rust patterns,它是由Lars Bergstrom编写的。
以下是实现双向链表的代码,来自@Yurume的Rust 1.12更新(未完全测试)
Playground
bjp0bcyl2#
现在在Rust标准库collections::dlist中有一个双向链表实现。它附带了一个完整的测试套件,是一个令人愉快的阅读和可用的工具。
Here is a link to the source.
正如评论中所建议的,以下是源代码本身(为简洁起见,省略了测试,因此请阅读链接(如果可用)):
免责声明:我 * 不是 * 这段代码的作者,它是Rust语言标准库的一部分。我不接受任何荣誉(或指责)。
tv6aics13#
另外,对于任何发现这个问题的人来说,对我的问题最清晰和最简单的答案是“使用 *”。
参见:http://static.rust-lang.org/doc/0.9/rust.html#pointer-types
也就是说,一个普通的指针可以有NULL值,谁的使用是1)不安全的,2)对其他对象的生命周期没有影响。
两个方向的链表将被实现为:
其中_prev值使用以下函数设置:
显然,这是非常混乱的,但它确实是处理涉及指针的事情的推荐方法。
从Lars Bergstrom的谈话中(在公认的答案中)得到的关键是,只要它们被仔细地编写并安全地 Package 到类型的内部实现中,这样做就可以了,继续公开一个“安全”的公共API。