前言
前一节我们分析了deque
的基本使用, 本节我们来分析一下deque
的对map
的操作, 即插入, 删除等. 但是本节只分析push, pop和删除操作, 而insert
操作有点复杂还是放到下节来分析.
push, pop
因为deque
的是能够双向操作, 所以其push和pop操作都类似于list
都可以直接有对应的操作. 需要注意的是list
是链表, 并不会涉及到界线的判断, 而deque
是由数组来存储的, 就需要随时对界线进行判断.
push实现.
template <class T, class Alloc = alloc, size_t BufSiz = 0>
class deque {
...
public: // push_* and pop_*
// 对尾进行插入
// 判断函数是否达到了数组尾部. 没有达到就直接进行插入
void push_back(const value_type& t) {
if (finish.cur != finish.last - 1) {
construct(finish.cur, t);
++finish.cur;
}
else
push_back_aux(t);
}
// 对头进行插入
// 判断函数是否达到了数组头部. 没有达到就直接进行插入
void push_front(const value_type& t) {
if (start.cur != start.first) {
construct(start.cur - 1, t);
--start.cur;
}
else
push_front_aux(t);
}
...
};
如果判断数组越界, 就移动到另一个数组进行push操作.
注意 : push_back
是先执行构造在移动node, 而push_front
是先移动node在进行构造. 实现的差异主要是finish
是指向最后一个元素的后一个地址而first
指向的就只第一个元素的地址. 下面pop也是一样的.
// Called only if finish.cur == finish.last - 1.
// 到达了数组的尾部
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t) {
value_type t_copy = t;
reserve_map_at_back();
// 申请空间
*(finish.node + 1) = allocate_node();
__STL_TRY {
// 执行构造
construct(finish.cur, t_copy);
// 移动node, 指向下一个数组的头
finish.set_node(finish.node + 1);
finish.cur = finish.first; // cur只指向当前数组的头
}
// 如果分配失败, 释放掉该内存
__STL_UNWIND(deallocate_node(*(finish.node + 1)));
}
// Called only if start.cur == start.first.
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t) {
value_type t_copy = t;
reserve_map_at_front();
// 申请空间
*(start.node - 1) = allocate_node();
__STL_TRY {
// 先要移动node, 让其指向上一个数组的尾部
start.set_node(start.node - 1);
// cur指向当前数组的尾部
start.cur = start.last - 1;
// 执行构造
construct(start.cur, t_copy);
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
start.set_node(start.node + 1);
start.cur = start.first;
deallocate_node(*(start.node - 1));
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
}
pop实现.
template <class T, class Alloc = alloc, size_t BufSiz = 0>
class deque {
...
public:
// 对尾部进行操作
// 判断是否达到数组的头部. 没有到达就直接释放
void pop_back() {
if (finish.cur != finish.first) {
--finish