位于 llvm/include/llvm/[[ADT]]/[[ilist.h]] html
参见:
* http://llvm.org/docs/ProgrammersManual.html#dss_ilist
* [[ilist.h]], [[ilist]]
* intrusive -- 侵入的、贯入的、打扰的、闯入的。node
== 简介 ==
ilist/iplist 被称为是侵入式的(intrusive),缘由在于它要求其模板参数类 T 里面提供有 next/prev 指针,而且实现 getNext(), setNext(), getPrev(), setPrev() 的函数。ide
ilist_iterator 模板类用于实现 ilist/iplist 的遍历。函数
其实现可看作是一个典型的 std list 容器类。参见 std。测试
<B>缺点</B>:须要 T 提供缺省构造,用于产生哨兵(sentinel)节点,及提供 getNext(), getPrev() 等函数用于访问 prev/next 节点。this
iplist - list 容器的子集。可用于多态类,也即有一个公共基类 其保存 next/prev 指针。ilist 自身只是保存了一个链表 list 的头指针。指针
== 类概要 ==
<syntaxhighlight lang="cpp">
template<typename NodeTy, typename Traits=ilist_traits<NodeTy> >
class iplist : public Traits { // 注1
Node_Type *Head; // 注2.链表第一个元素指针。
pointer, reference 等 STL 标准容器类型定义。
this(), ~this() // 注3。构造,析构。
begin(), end(), size(), empty(), front(), back() 等标准容器方法。
push(), pop(), swap(), insert(), erase(), remove() 等操纵方法。
splice(), erase_if(), unique(), merge(), sort() 等列表常见方法。
}
</syntaxhighlight>htm
* 注1:使用 Traits 做为基类,其提供 next,prev,sentinel,node 访问策略。
* 注2:链表的 Head 元素在构造时,使用 Traits 提供的策略初始化。
** 通常当新建一个 iplist 的时候,Head == null,没有构造 sentinel 节点。仅当访问 begin(), push() 等方法须要的时候,才会''延迟''建立 sentinel 节点。
** Head.prev 指向 sentinel 节点。 sentinel.prev 指向链表的 Last 节点。
** sentinel.next 为 null。对象
* 注3:构造中初始化 Head,使用 Traits 中提供的策略方法;析构中使用 Traits 中方法删除节点,及销毁 sentinel 哨兵节点。参见 [[ilist_traits]]
* 注4:size() 方法会遍历全部节点统计数量,因此效率会比较低。也许新策略容许若是保存一个 size 字段更好?
* 注5:sizeof(iplist<T>) 通常是 4,也即 Head 指针的大小。若是 Traits 特化保存有数据,则 sizeof() 可能不是这个值。这种状况出如今 ilist_traits<Value> 特化中。继承
== iplist 更多说明 ==
模板类 iplist 有以下的三个有趣的状态:
* 1. 链表未构造任何节点状态。此状况下,Head 指针为 null。在此状况下,任何对枚举器的获取(如调用 begin(), end() 等方法)都会透明地转换到状态2.
* 2. 链表为空(empty),但包含一个哨兵(sentinel)节点,以实现 end 枚举器指针。这个哨兵节点经过 Traits::createSentinel() 方法建立,而后连接到 iplist 的末尾。当列表处于这个 empty 空状态的时候,Head 指针指向哨兵节点。哨兵节点一旦建立,则直到列表析构的时候才会被删除。
* 3. 链表可能包含实际的对象,其使用节点双向连接列表链接。一个不变的状况是:列表的第一个节点(Head)的 prev 指针老是指向链表的最后一个节点(哨兵节点),哨兵节点的 next 指针老是 null。
额外:
* 画出图会更清晰一些。
* 用 VC2010 测试的时候,还有一个小编译错误: warning C4355: “this”: 用于基成员初始值设定项列表。在这里: iplist() : Head(this->provideInitialHead()) 。
== ilist ==
模板类 ilist 继承自 iplist<T>,并对其进行了一些小的扩展:
* 提供新的多种构造方式。
* 提供 insert() 的传递引用参数 const T& 重载形式。iplist 使用的是 T* 指针参数。使用这种 insert 须要提供复制构造,如 Value(const Value&).
* ilist 对于 [[Value]], [[GlobalVariable]], [[Instruction]] 等类构成的双向链表特别合适。