list
G2.9版本
list底层实现为双向循环链表,并且环状链表的尾端还有一个空白节点,这个空白节点代表迭代器指向的节点,由此可得end()指向迭代器节点,begin()指向迭代器下一个节点(IterType)((node).next)。符合STL迭代器前开后闭的原则
可以看到在G2.9版本中list的iterator引入了三个模板参数分别为T,T&,T。但其可以用一个模板参数T表示,在G4.9可以看到改进
template <class T, class Alloc = alloc>
class list{
protected:
typedef __list_node<T> list_node;
public:
typedef list_node* link_type;
typedef __list_iterator<T, T&, T*> iterator;
protected:
link_type node;
.....
};
template <class T>
struct __list_node{
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
};
template <class T, class Ref, class Ptr>
struct __list_iterator{
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
.....
};
源码解析:
- G2.9中包含一个头结点link_type node,其指向链表的头结点,由于成员为指针,sizeof(list< int>)大小为4
- list节点类型为_list_node< T>,内置指针类型为void*,后续需要类型转换,G4.9中采用了对象本身的指针
list中的Iterator设计
template <class T, class Ref, class Ptr>
struct __list_iterator{
typedef __list_iterator<T, Ref, Ptr> self;
typedef bidirectional_iterator_tag iterator_category;//1
typedef T value_type;//2
typedef Ptr pointer;//3
typedef Ref reference;//4
typedef __list_node<T>* link_type;
typedef ptrdiff_t difference_type;//5
link_node node;
reference operator*() const { return (*node).data; }
pointer operator->() const { return &(operator*()); }
self& operator++()
{ node = (link_type)((*node).next); return *this; }
self operator++(int)
{ self tmp = *this; ++*this; return tmp; }
......
};
- 可以看到迭代器中有typedef和操作符重载,其中5个typedef在每个迭代器中都必须具备,提供给算法iterator::value_type(元素类型),iterator::difference_type(迭代器距离,即指针之间的最大距离),iterator::iteraor_category(迭代器类型,这里为bidirectional_iterator_tag),剩余两个在STL算法中还没有用到
- ++重载前缀和后缀区别(1)返回引用与返回值(2)后缀有int参数
- ->在编译器中有特殊处理,调用
ite->method();
时,ite->调用operator->返回对象指针,编译器在自动添加一个->,调用对象的方法 - 在几乎所有迭代器中,difference_type的值都为ptrdiff_t,为内存中指针的最大寻址范围
- 注意:在operator++(int)函数中的
self tmp = *this;
实际操作时并不会唤起operator*(),因为编译器在遇见=时会唤起copy ctor创建tmp并以*this为初值,*this
已经被解释为ctor的参数。++*this;
时也将*this
解释为operator++()的参数,在最后return *this;
时调用拷贝函数,返回值。
G4.9版本
虽然也是双向循环链表,但包含了许多继承和复合关系
首先list继承自_List_base< _Tp, _A>,_List_base< _Tp, _A>中包含一个_List_impl< _Tp, _A>成员,这个成员中包含_List_node_base< _Tp>成员。其中_List_node_base< _Tp>内部有两个指针pre和next,代表尾后迭代器指向的空节点,即end()返回的迭代器指向节点。而普通节点类型为_List_node< _Tp>,继承自_List_node_base< _Tp>,里面多了一个数据域。
template<typename _Tp,
typename _Alloc = std::allocator<_Tp>>
class list:protected _List_base<_Tp, _Alloc>
{
public:typedef _List_iterator<_Tp> iterator;
......
};
template<typename _Tp>
struct _List_iterator
{
typedef _Tp* pointer;
typedef _Tp& reference;
......
};
struct _List_node_base
{
_List_node_base* _M_next;
_List_node_base* _M_prev;
};
template<typename _Tp>
struct _List_node
: public _List_node_base
{
_Tp _M_data;
};