本文章内容来源于《STL源码分析》第四章
3.4 deque的元素操作
3.4.1 deque的前和尾部删除
- pop_back()
- pop_front()
// pop
void pop_back(){
if(finish.cur != finish.start){ // 最后缓冲区还有一个以上的元素
-- finish.cur; // 调整指针;
destroy(finish.cur);// 最后元素析构
}else{
// 最后缓冲区没有元素
pop_back_aux(); // 释放缓冲区
}
}
void pop_front(){
if(start.cur != start.last -1){// 第一缓冲区还有多个元素
destroy(start.cur);
++ start.cur;
}else{ // 第一缓冲区只有一个元素
pop_front_aux(); // 释放缓冲区
}
}
这两个函数依然是借助了辅助函数:
// pop_back_aux
void pop_back_aux(){
deallocate_node(finish.first); // 释放最后一个缓冲区
finish.set_node(finish.node -1); // 调整finish的指向
finish.cur = finish.last -1;
destroy(finish.cur); // 析构该元素
}
//pop_front_aux
void pop_front_aux(){
destroy(start.first); // 第一缓冲区第一个元素析构
deallocate_node(start.first) ; // 释放第一缓冲区
start.set_node(start.node + 1);
start.cur = start.first; // 下一个缓冲区第一个元素
}
- 在删除元素的时候,也要考虑缓冲区的释放
3.4.2 clear()
// 清除deque,保留一个缓冲区
void clear(){
// 针对头和尾部中间的缓冲区,都是饱满的
for(map_pointer node = start.node +1; node<finish.node ; ++node){
// 析构所有元素
destroy(*node, *node+buffer_size());
// 释放缓冲区
data_allocator::deallocate(*node,buffer_size());
}
if(start.node !=finish.node){ // 还有头和尾部两个缓冲区
destroy(start.cur, start.last); // 将头部缓冲区所有元素析构
destroy(finish.first, finish.cur); // 尾部缓冲区析构
// 释放掉尾部缓冲区,头部缓冲区保留
data_allocator::deallocate(finish.start, buffer_size());
}else{ // 只有一个缓冲区
destroy(start.cur, finish.cur); // 所有元素析构
finish = start; // 调整状态
}
}
3.4.3 erase
// erase 操作
iterator erase(iterator pos){
iterator next = pos;
++next;
difference_type index = pos - next; // 清除点之前的元素个数
if(index <(size() >>1 )){
copy_backward(start,pos, next); // 移动清除之前的元素
pop_front(); // 消除最前的一个元素
}else{
copy(next, finish, pos); // 移动清除之后的元素
pop_back();
}
return start+ index;
}
// erase [first, last)
void erase(iterator first, iterator last){
if(first == start && last == finish){ // 如果是清除整个deque
clear();
return finish;
}else{
difference_type n = last - first;
difference_type elems_before = first - start; // 清除区间前方的元素个数
if(elems_before < (size() -n) /2){ // 前方元素比较少
copy_backward(start, first, last);
iterator new_start = start +n; // 新起点
destroy(start, new_start); // 移动完毕,冗余元素析构
for(map_pointer cur = start.node; cur<new_start.node; ++cur){
data_allocator::deallocate(*cur, buffer_size());
}
start = new_start; // 设定deque的新起点
}else{
copy(last,finish, first); // 向前移动后方元素
iterator new_finish = finish - n;
destroy(new_finish , finish); // 移动完成冗余析构
for(map_pointer cur = new_finish.node +1;cur <=finish.node; ++cur){
data_allocator::deallocate(*cur, buffer_size());
}
finish = new_finish ; // deque 新尾部
}
return start + elems_before;
}
}
4 迭代器的操作
/**
deque 的迭代器
*/
template<class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator{
typedef __deque_iterator<T, T&,T*, BufSiz> iterator;
typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T));}
// 未继承std::iterator, 必须自行添加iterator_category
typedef random_access_iterator_tag iterator_category;
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; // 迭代器指向缓冲区的current 元素
T* first; // 指向缓冲区的头;
T* last; // 指向缓冲区的尾巴(含备用空间)
map_pointer node; // 指向管理中心
public:
void set_node(map_pointer new_node){
node = new_node;
first =*new_node; // 缓冲区开头
last = first + difference_type(buffer_size());
}
// 运算符重载
reference operator*() const{return *cur;}
pointer operator->() const{return &(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);
// first< cur -n <= offset <= cur +n < last
// 目标位置在同一缓冲区
if(offset >= && 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 ){
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);
}
boll operator<(const self& x)const{
return (node == x.node) ? (cur < x.cur) :(node < x.node);
}
};