00 写在前面
说完vector,也了解了分配器(alloctor),接下来我们说说比较具有代表性的容器list。
【STL源码剖析】总结笔记(3):vector初识
【STL源码剖析】总结笔记(4):幕后功臣–分配器(allocator)
为什么说具有代表性呢,因为list的空间不再连续,对空间的使用也更加精准。
学习list也是帮助我们打开迭代器大门的第一步。
01 概述
list和vector是我们平时最常使用的容器。list就是链表,而且根据前置知识我们知道list是一个双向链表。
list的节点
假如让我们设计一个双向链表,我们肯定会先设计它的节点结构。在节点结构里包含向前的指针和向后的指针。
是的,在STL里也是这样的。
template <class T>
struct _list_node{
typedef void * void_pointer;
void_pointer prev;
void_pointer next;
T data;
}
当然,这里的void写为_list_node可能更加合适,更符合我们的设计规范。
list的数据结构
list是一个环状双向链表,先上图:
为了符合“前闭后开”的要求,这里故意在尾端设置了一个虚节点。
而整个环形链表结构只需要一个指针就可以遍历了,也就是node。node就是上图中红色的部分,指向虚节点。
template <class T,class Alloc=alloc>
class list{
protected:
typedef _list_node<T> list_node;
public:
typdef list_node * link_type;
protected:
link_type node;
}
同理,begin()和end()就可以通过node实现了。
iterator begin(){
return (link_type)((*node).next);//注意begin()是存在的,而end()不存在,所以类型不同
}
iterator end(){
return node;}
empty(),size(),front()(头节点内容),back()(尾节点内容)都比较好实现。
bool empty() const{
return node->next==node;
}
size_type size() const {
size_type result = 0;
distance(begin(