一.模型
vector维护的是连续线性空间,当空间大小不足时,另辟一块更大的内存,将之前空间的所有元素移至新空间,并销毁释放原空间。stl中list是一个环状双向链表,它维护的不是连续空间,而是一个个的节点(__list_node),节点之间通过指针连接。deque维护的也是连续线性空间,不过不同于vector,它的空间是分段连续的,当空间大小不足时,deque可以另辟一块空间,并与原来的空间通过中控器链接起来。
具体模型:
vector的空间模型
list的空间模型
deque的空间模型
二.迭代器
在http://blog.youkuaiyun.com/u010772289/article/details/52430415 中讲述过迭代器有五种类型,分别为Input Iterator(只读),Output Iterator(只写),Forward Iterator(前向移动),Bidirectional Iterator(双向移动),Random Access Iterator(双向跳跃移动)
vector的迭代器是一个普通指针,普通指针支持双向跳跃移动,因此符合vector随机存取的特性。list的迭代器是必须具备前移后移的能力,即为Bidirectional Iterator,它不能选择普通的指针作为迭代器,需要自己另外定义迭代器类。deque维护的是分段连续空间,其迭代器支持双向随意移动,因此需要是Random Access Iterator,但它不能选择普通指针作为迭代器,因为deque的迭代器一旦到达缓冲区的边缘,它前进或后退时必须得跳跃到下一个或上一个缓冲区。
list的节点以及迭代器定义如下:
template <class T>
struct __list_node {
typedef void* void_pointer;
void_pointer next;
void_pointer prev;
T data;
};
template<class T, class Ref, class Ptr>
struct __list_iterator {
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
typedef __list_iterator<T, Ref, Ptr> self;
typedef bidirectional_iterator_tag iterator_category; //迭代器类型:Bidirectional Iterator
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef __list_node<T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
link_type node;
__list_iterator(link_type x) : node(x) {}
__list_iterator() {}
__list_iterator(const iterator& x) : node(x.node) {}
bool operator==(const self& x) const { return node == x.node; }
bool operator!=(const self& x) const { return node != x.node; }
reference operator*() const { return (*node).data; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
self& operator++() {
node = (link_type)((*node).next);
return *this;
}
self operator++(int) {
self tmp = *this;
++*this;
return tmp;
}
self& operator--() {
node = (link_type)((*node).prev);
return *this;
}
self operator--(int) {
self tmp = *this;
--*this;
return tmp;
}
};
可以看出,list的是双向链表,其节点中定义了一个指向上一个节点的指针prev以及指向下一个节点的指针next。其迭代器类型(iterator_category)为bidirectional_iterator_tag(它是一个struct类,定义在stl_iterator.h中,表示可双向移动的迭代器类型,参考http://blog.youkuaiyun.com/u010772289/article/details/52430415),另外为了支持list的迭代器前向/后向移动的特性,需要重载++,–等运算符。
deque的迭代器定义如下:
#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
template <class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
typedef __deque_iterator<T, T&, T*, BufSiz> iterator; //iterator
typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;//const_iterator
static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); } //缓冲区大小
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
template <class T, class Ref, class Ptr>
struct __deque_iterator {
typedef __deque_iterator<T, T&, T*> iterator;
typedef __deque_iterator<T, const T&, const T*> const_iterator;
static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }
#endif
typedef random_access_iterator_tag iterator_category;//定义iterator_category,供iterator_traits用 为何此文件未包含random_access_iterator_tag所在头文件"stl_iterator"????
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T** map_pointer; //指向中控器的指针
typedef __deque_iterator self;
T* cur; //缓冲区中当前指针
T* first; //缓冲区头指针
T* last; //缓冲区尾指针
map_pointer node;
__deque_iterator(T* x, map_pointer y) //__deque_iterator构造函数
: cur(x), first(*y), last(*y + buffer_size()), node(y) {} //缓冲区当前指针,头指针,尾指针
__deque_iterator() : cur(0), first(0), last(0), node(0) {}
__deque_iterator(const iterator& x) //拷贝构造函数
: cur(x.cur), first(x.first), last(x.last), node(x.node) {}
reference operator*() const { return *cur; } //const成员函数
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
difference_type operator-(const self& x) const {
return difference_type(buffer_size()) * (node - x.node - 1) +
(cur - first) + (x.last - x.cur);
}
self& operator++() {
++cur;
if (cur == last) {
set_node(node + 1);
cur = first;
}
return *this;
}
self operator++(int) {
self tmp = *this;
++*this;
return tmp;
}
self& operator--() {
if (cur == first) {
set_node(node - 1);
cur = last;
}
--cur;
return *this;
}
self operator--(int) {
self tmp = *this;
--*this;
return tmp;
}
self& operator+=(difference_type n) {
difference_type offset = n + (cur - first);
if (offset >= 0 && offset < difference_type(buffer_size()))
cur += n;
else {
difference_type node_offset =
offset > 0 ? offset / difference_type(buffer_size())
: -difference_type((-offset - 1) / buffer_size()) - 1;
set_node(node + node_offset);
cur = first + (offset - node_offset * difference_type(buffer_size()));
}
return *this;
}
self operator+(difference_type n) const {
self tmp = *this;
return tmp += n;
}
self& operator-=(difference_type n) { return *this += -n; }
self operator-(difference_type n) const {
self tmp = *this;
return tmp -= n;
}
reference operator[](difference_type n) const { return *(*this + n); }
bool operator==(const self& x) const { return cur == x.cur; }
bool operator!=(const self& x) const { return !(*this == x); }
bool operator<(const self& x) const {
return (node == x.node) ? (cur < x.cur) : (node < x.node);
}
void set_node(map_pointer new_node) { //切换至正确的节点,即缓冲区
node = new_node;
first = *new_node;
last = first + difference_type(buffer_size());
}
};
因为deque的迭代器支持双向随意移动,因而重载了++ , – ,+, - 等运算符。当迭代器移动超出当前缓冲区范围时,需要切换至其它节点(函数set_node)。