deque除了维护一个先前说过的指向map的指标外,也维护start,finish两个迭代器,分别指向第一个缓冲区的第一个元素和最后缓冲区的最后一个元素(的下一位置)。此外它当然也必须记住目前的map大小。因为一旦map所提供的节点不足,就必须重新配置更大的一块map。
// deque的数据结构
template
class deque
{
public: // Basic types
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
public: // Iterators
typedef __deque_iterator iterator;
protected: // Internal typedefs
typedef pointer* map_pointer;
// 这个提供STL标准的allocator接口, 见
typedef simple_alloc data_allocator;
typedef simple_alloc map_allocator;
// 获取缓冲区最大存储元素数量
static size_type buffer_size()
{
return __deque_buf_size(BufSiz, sizeof(value_type));
}
static size_type initial_map_size() { return 8; }
protected: // Data members
iterator start; // 起始缓冲区
iterator finish; // 最后一个缓冲区
// 指向map, map是一个连续的空间, 其每个元素都是一个指针,指向一个节点(缓冲区)
map_pointer map;
size_type map_size; // map容量
...
}
有了上述结构,以下数个机能便可轻易完成:
iterator begin() { return start; }
iterator end() { return finish; }
// 提供随机访问能力, 其调用的是迭代器重载的operator []
// 其实际地址需要进行一些列的计算, 效率有损失
reference operator[](size_type n) { return start[difference_type(n)]; }
reference front() { return *start; }
reference back()
{
iterator tmp = finish;
--tmp;
return *tmp;
}
//没有直接调用finish-1是因为调用层次太深
// 当前容器拥有的元素个数, 调用迭代器重载的operator -
size_type size() const { return finish - start;; }
size_type max_size() const { return size_type(-1); }
// deque为空的时, 只有一个缓冲区
bool empty() const { return finish == start; }
typedef pointer* map_pointer;
// 这个提供STL标准的allocator接口, 见
typedef simple_alloc data_allocator;
typedef simple_alloc map_allocator;
// 获取缓冲区最大存储元素数量
static size_type buffer_size()
{
return __deque_buf_size(BufSiz, sizeof(value_type));
}
static size_type initial_map_size() { return 8; }
deque(int n, const value_type& value)
: start(), finish(), map(0), map_size(0)
{
fill_initialize(n, value);
}
deque::fill_initialize函数:
// 分配n个结点, 并以value为元素值初始化
template
void deque::fill_initialize(size_type n,
const value_type& value)
{
create_map_and_nodes(n); // 配置map和缓冲区
map_pointer cur;
__STL_TRY {
// 为每一个缓冲区设定初值
for (cur = start.node; cur < finish.node; ++cur)
uninitialized_fill(*cur, *cur + buffer_size(), value);
// 尾端可能留有备用空间,不必设初值
uninitialized_fill(finish.first, finish.cur, value);
}
catch (...) {
for (map_pointer n = start.node; n < cur; ++n)
destroy(*n, *n + buffer_size());
destroy_map_and_nodes();
throw;
}
}
deque::create_map_and_nodes函数:
// 创建内部使用的map,并配置每一个缓冲区
template
void deque::create_map_and_nodes(size_type num_elements)
{
// 需要的结点数, 元素个数 / 每个缓冲区能容纳的元素数 + 1
// 这里如果能整除,会多分配一个
size_type num_nodes = num_elements / buffer_size() + 1;
// map要维护的结点, 这里最小的值为8,最多为所需节点数+1,前后各留一个以便扩充
map_size = max(initial_map_size(), num_nodes + 2);
// 调用deque专属空间配置器,配置map空间
map = map_allocator::allocate(map_size);
// 将[nstart, nfinish)区间设置在map的中间,
// 这样就能保证前后增长而尽可能减少map的重新分配次数
map_pointer nstart = map + (map_size - num_nodes) / 2;
map_pointer nfinish = nstart + num_nodes - 1;
// 分配结点空间
map_pointer cur;
__STL_TRY {
for (cur = nstart; cur <= nfinish; ++cur)
// 为每一个map指针指向的缓冲区的每一个元素分配内存空间
*cur = allocate_node();
}
// 维护指针状态,为deque的两个迭代器start和finish赋初值
start.set_node(nstart);
finish.set_node(nfinish);
start.cur = start.first;
finish.cur = finish.first + num_elements % buffer_size();
}