protected:

typedef simple_alloc<value_type,Alloc> data_allocator;

//用来配置元素的alloc

typedef simple_alloc<pointer,Alloc> map_allocator;

//用来配置指针的alloc

deque(int n,const value_type& value)

:start(),finish(),map(),map_size()

{

fill_initialize(n,value);

}

//fill_initialize

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::fill_initialize(size_t n,

const value_type& value)

{

//可以分配一定数量(略大于需求量)的内存

create_map_and_nodes(n);

map_pointer cur;

__STL_TRY

{

//这里初始化start之后finish之前的所有元素

//这里的cur不是元素,而是一个map_ponter,*cur才是node (*cur).cur才是元素

for(cur=start.node;cur<finish.node;++cur)

uninitialized_fill(*cur,*cur+buffer_size(),value);

//最后一块缓存区(finish)不一定全部有元素,所以只要初始化到finish.cur前面一个的位置

uninitialized_fill(finish.first,finish.cur,value);

}

catch(...)

{

...

}

}

//create_map_and_nodes

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::create_map_and_nodes(size_type num_elements)

{

//得到缓存区的数量

size_type num_nodes=num_elements / buffer_size() +
;

//取 8

缓存区数量+2

map_size = max(initial_map_size(),num_nodes +
);

//分配map_size大小(所以node)的内存

map=map_allocator::allocate(map_size);

//    map_size - num_nodes ==
已经分配的内存中 不需要初始化的部分

//    (map_size - num_nodes) / 2
表示前后各一半

map_pointer nstart = map + (map_size - num_nodes) /
;

map_pointer nfinish = nstart + num_nodes -;

//cur:{T**}

map_pointer cur;

__STL_TRY

{

//pointer allocate_node(){return data_allocator::allocate(buffer_size());}

//分配buffer_size()大小(一个缓存区大小)的内存

for(cur=nstart;cur <= nfinish;++cur)

{

*cur=allocate_node();

}

}

catch(...)

{

...

}

start.set_node(nstart);

finish.set_node(nfinish);

start.cur=start.first;

finish.cur=finish.first + num_elements % buffer_size();

}

//push_back

public:

void push_back(const value_type& t)

{

)

{

//使用finish缓存区的未使用空间,构造元素

//如果是必要的
会一个个调用构造函数,不然就一起构造了

construct(finish.cur , t);

++finish.cur;

}

else

//当finish只剩下
一个一下
的空间时调用(最后一个使last不能存数据,

//使finish能指向一个空的缓存区

push_back_aux(t);

}

//push_back_aux

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 +
) = allocate_node();

__STL_TRY

{

construct(finish.cur , t_copy);

finish.set_node(finish.node +
);

finish.cur = finish.first;

}

//deallocate_node(pointer n){ data_allocator::deallocate(n,buffer_size());}

__STL_UNWIND(deallocate_node(*(finish.node +
)));

}

//push_front

void push_front(const value_type& t)

{

if(start.cur != start.first)

{

construct(start.cur-,t);

--start.cur;

}

else

push_front_aux(t);

}

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 -
) = allocate_node();

__STL_TRY

{

start.set_node(start.node -
);

start.cur=start.last -
;

construct(start.cur , t_copy);

}

catch(..)

{

start.set_node(start.node +
);

start.cur=start.first;

//deallocate_node(pointer n){ data_allocator::deallocate(n,buffer_size());}

deallocate_node(*(start.node -
));

}

}

void reserve_map_at_back (size_type nodes_to_add =
)

{

//  l= map + map_size ==最后的node之后一个越界的node

//  l-finish.node -1 ==
剩下的node个数

//  nodes_to_add > l - finish.node -1
不需要重新分配内存

> map_size - (finish.node - map))

reallocate_map(nodes_to_add,false);//false表示在尾部重分配

}

void reserve_map_at_front (size_type nodes_to_add =
)

{

//同上

if(nodes_to_add  >start.node - map)

reallocate_map(nodes_to_add,true);

}

//reallocate_map

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::reallocate_map(size_type nodes_to_add,

bool add_at_front)

{

size_type ole_num_nodes = finish.node - start.node +
;

size_type new_num_nodes = ole_num_nodes + nodes_to_add;

map_pointer new_nstart;//T**类型

* new_num_nodes)

{   //剩余的node内存数量是
两倍的
新的node数量
时调用

/*

最后要使头尾剩下的可分配(未使用)的node数量一样

如果是add_at_front
接下来会在头部添加 nodes_to_add数量的node

如果是add_at_front
接下来会在尾部添加

说到底
这个reallocate函数并不添加node,他的使命是确保有足够的

nodes给前面的aux函数使用

*/

new_nstart = map + (map_size - new_num_nodes) /

+ (add_at_front ? nodes_to_add :
);

//防止覆盖问题

if(new_nstart < start.node)

copy(start.node , finish.node +
, new_nstart);

else

copy_backward(start.node, finish.node +
, new_nstart + ole_num_nodes);

}

else

{   //剩下的没有两倍就
重新分配一块nodes内存

//新的缓存区起码要留map_size+2
的大小

size_type new_map_size = map_size + max(map_size, nodes_to_add) +
;

map_pointer new_map =map_allocator::allocate(new_map_size);

//同上

new_nstart = new_map + (new_map_size - new_num_nodes) /

+ (add_at_front ? nodes_to_add :
);

copy(start.node, finish,node +, new_nstart);

map_allocator::deallocate(map,map_size);

map=new_map;

map_size = new_map_size;

}

start.set_node(new_nstart);

finish.set_node(new_nstart + ole_num_nodes);

}

//pop_back

void pop_back()

{

if(finish.cur != finish.first)

{

--finish.cur;

destroy(finish.cur);

}

else

pop_back_aux();

}

//pop_back_aux

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::pop_back_aux()

{

//释放finish的缓存,使finish指向前一个node末尾

//deallocate_node(pointer n){ data_allocator::deallocate(n,buffer_size());}

deallocate_node(finish.first);

finish.set_node(finish.node -
);

finish.cur = finish.last -;

destroy(finish.cur);

}

//pop_front

void pop_front()

{

)

{

destroy(start.cur)

++start.cur;

}

else

pop_front_aux();

}

//pop_front_aux

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::pop_front_aux()

{

destroy(start.cur);

deallocate_node(start.first);

start.set_node(start.node +);

start.cur = start.first;

}

//clear

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::clear()

{

; node < finish.node; ++node)

{

//先析构,再清除内存

destroy(*node, *node + buffer_size());

data_allocator::deallocate(*node, buffer_size());

}

if(start.node != finish.node)

{//在clear之前有大于等于两个node时调用

destroy(start.cur, start.last);

destroy(finish.first, finish.cur);

data_allocator::deallocate(finish.first, buffer_size());

}

else

{//在clear之前finish
和start指向同一个node;

destroy(start.cur, finish.cur);

}

//前面都保存了一个node的内存,没有释放所有内存

finish = start;

}

//erase

iterator erase(iterator pos)

{

iterator next = pos;

++next;

diffenrence_type index = pos - start;

))

{//如果前面元素少,就从前开始拷贝前面的元素来填充(覆盖)当前元素,反之就从后开始拷贝

copy_backward(start, pos, next);

pop_front();

}

else

{

copy(next, finish, pos);

pop_back();

}

return start + index;

}

//erase 区间

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::erase(iterator first, iterator last)

{

if(first == start && last == finish)

{//如果是全部删除
直接调用clear()

clear();

return finish;

}

else

{

diffenrence_type n = last - first;

//最开始的元素到要删除的迭代器的第一个元素的元素个数

diffenrence_type elems_before = first -start;

)

{//前面的元素比较少就调用

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());

setart = new_start;

}

else

{

copy(last, finish,first);

iterator new_finish = finish -n;

destroy(new_finish, finish);

; cur< finish.node; ++cur)

data_allocator::deallocate(*cur, buffer_size());

finish  = new_finish;

}

return start + elems_before;

}

}

iterator insert(iterator position,
const value_type& x)

{

if(position.cur == start.cur)

{

push_front(x);

return start;

}

else if(position.cur == finish.cur)

{

push_back(x);

iterator tmp = finish;

--tmp;

return tmp;

}

else

{

return insert_aux(position,x);

}

}

//insert_aux

template<class T,class Alloc,size_t BufSize>

void deque<T,Alloc,BufSize>::insert_aux(iterator pos,
const value_type& x)

{

diffenrence_type index = pos - start;

value_type x_copy = x;

)

{//哪边元素少就移动哪边

//新加一个元素到头部

push_front(front());

//设置要移动的各项位置

iterator front1 = start;

++front1;

iterator front2 = front1;

++front2;

//由于新加了一个元素
内存结构发生变化
所以要重新给pos赋值

pos = start + index;

iterator pos1 = pos;

++pos1;

//把从原先第一个元素到原先pos的元素都往前移动一格的位置

copy(front2, pos1, front1);

}

else

{

//几乎同上

push_back(back());

iterator back1 = finish;

--back1;

iterator back2 = back1;

--back2;

pos = start + index;

copy_backward(pos, back2, back1);

}

*pos = x_copy;

return pos;

}

stl源码剖析 详细学习笔记deque(3)的更多相关文章

  1. stl源码剖析 详细学习笔记deque(2)

    //---------------------------15/3/13---------------------------- self&operator++() { ++cur; if(c ...

  2. stl源码剖析 详细学习笔记deque(1)

    //--------------------------15/3/12---------------------------- deque { deque没有容量(capacity)观念,是动态分段的 ...

  3. stl源码剖析 详细学习笔记 hashtable

    //---------------------------15/03/24---------------------------- //hashtable { /* 概述: sgi采用的是开链法完成h ...

  4. stl源码剖析 详细学习笔记 set map

    // //  set map.cpp //  笔记 // //  Created by fam on 15/3/23. // // //---------------------------15/03 ...

  5. stl源码剖析 详细学习笔记 RB_tree (1)

    // //  RB_tree_STL.cpp //  笔记 // //  Created by fam on 15/3/21. // // #include "RB_tree_STL.h&q ...

  6. stl源码剖析 详细学习笔记priority_queue slist

    // //  priority_queue.cpp //  笔记 // //  Created by fam on 15/3/16. // // //------------------------- ...

  7. stl源码剖析 详细学习笔记heap

    // //  heap.cpp //  笔记 // //  Created by fam on 15/3/15. // // //---------------------------15/03/15 ...

  8. stl源码剖析 详细学习笔记stack queue

    // //  stack.cpp //  笔记 // //  Created by fam on 15/3/15. // // //---------------------------15/03/1 ...

  9. stl源码剖析 详细学习笔记 空间配置器

    //---------------------------15/04/05---------------------------- /* 空间配置器概述: 1:new操作包含两个阶段操作 1>调 ...

随机推荐

  1. python常用模块之-random模块

    random模块顾名思义就是生成随机数的模块. random模块有以下常见方法: 1,打印0-1之间的任意随机浮点数,不能指定区间. print(random.random()) 2,打印随机符点数, ...

  2. 使用SQL Server Management Studio操作replication时,要用机器名登录,不要用IP地址

    如果你在使用SSMS(SQL Server Management Studio)登录SQL Server时,使用的是IP地址,如下图所示: 当你操作replication时,会报错: 从上面的错误提示 ...

  3. SQL Server中事务transaction如果没写在try catch中,就算中间语句报错还是会提交

    假如我们数据库中有两张表Person和Book Person表: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ) NULL, [CreateTi ...

  4. 开发中解决Access-Control-Allow-Origin跨域问题的Chrome神器插件,安装及使用

    背景: 笔者在用cordova开发安卓程序的时候在安卓设备上不存在跨域问题,但是在浏览器端模拟调试的时候却出现了Access-Control-Allow-Origin跨域问题,报错如下 No 'Acc ...

  5. __细看InnoDB数据落盘 图解 MYSQL

    http://hatemysql.com/?p=503 1.  概述 前面很多大侠都分享过MySQL的InnoDB存储引擎将数据刷新的各种情况.我们这篇文章从InnoDB往下,看看数据从InnoDB的 ...

  6. sql server数据导入导出方法统计

    常用的数据量不是很大的情况的几种方法:转载地址 http://www.cnblogs.com/changbluesky/archive/2010/06/23/1761779.html 大数据量的推荐导 ...

  7. nc 命令使用详解

    nc 命令介绍: Ncat is a feature-packed networking utility which reads and writes data across networks fro ...

  8. 【转】学习Linux守护进程详细笔记

    [原文]https://www.toutiao.com/i6566814959966093837/ Linux守护进程 一. 守护进程概述 守护进程,也就是通常所说的Daemon进程,是Linux中的 ...

  9. SQL SERVR 逻辑函数

    IIF: 根据布尔表达式计算为 true 还是 false,返回其中一个值. IIF 是一种用于编写 CASE 表达式的快速方法. 它将传递的布尔表达式计算为第一个参数,然后根据计算结果返回其他两个参 ...

  10. 网络唤醒(WOL)全解指南:原理篇

    什么是网络唤醒 网络唤醒(Wake-on-LAN,WOL)是一种计算机局域网唤醒技术,使局域网内处于关机或休眠状态的计算机,将状态转换成引导(Boot Loader)或运行状态.无线唤醒(Wake-o ...