stl源码剖析 详细学习笔记deque(3)
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)的更多相关文章
- stl源码剖析 详细学习笔记deque(2)
//---------------------------15/3/13---------------------------- self&operator++() { ++cur; if(c ...
- stl源码剖析 详细学习笔记deque(1)
//--------------------------15/3/12---------------------------- deque { deque没有容量(capacity)观念,是动态分段的 ...
- stl源码剖析 详细学习笔记 hashtable
//---------------------------15/03/24---------------------------- //hashtable { /* 概述: sgi采用的是开链法完成h ...
- stl源码剖析 详细学习笔记 set map
// // set map.cpp // 笔记 // // Created by fam on 15/3/23. // // //---------------------------15/03 ...
- stl源码剖析 详细学习笔记 RB_tree (1)
// // RB_tree_STL.cpp // 笔记 // // Created by fam on 15/3/21. // // #include "RB_tree_STL.h&q ...
- stl源码剖析 详细学习笔记priority_queue slist
// // priority_queue.cpp // 笔记 // // Created by fam on 15/3/16. // // //------------------------- ...
- stl源码剖析 详细学习笔记heap
// // heap.cpp // 笔记 // // Created by fam on 15/3/15. // // //---------------------------15/03/15 ...
- stl源码剖析 详细学习笔记stack queue
// // stack.cpp // 笔记 // // Created by fam on 15/3/15. // // //---------------------------15/03/1 ...
- stl源码剖析 详细学习笔记 空间配置器
//---------------------------15/04/05---------------------------- /* 空间配置器概述: 1:new操作包含两个阶段操作 1>调 ...
随机推荐
- SQLServer导数据到Oracle
从SQLServer导数据到Oracle大概有以下几种方法: 使用SSMS的导出数据向导,使用Microsoft ODBC for Oracle或Oracle Provider for OLE DB连 ...
- Hyper-v UBUNTU 12.04 模板设置
Ubuntu 12.04 模板设置 参考文档 Hyper-v安装ubuntu http://blogs.msdn.com/b/virtual_pc_guy/archive/2012/05/02/ubu ...
- UNIX高级环境编程(12)进程关联(Process Relationships)- 终端登录过程 ,进程组,Session
在前面的章节我们了解到,进程之间是有关联的: 每个进程都有一个父进程: 子进程退出时,父进程可以感知并且获取子进程的退出状态. 本章我们将了解: 进程组的更多细节: sessions的内容: logi ...
- ln -s 软连接介绍
软连接(softlink)也称符号链接.linux里的软连接文件就类似于windows系统中的快捷方式.软连接文件实际上是一个特殊的文件,文件类型是I.软连接文件实际上可以理解为一个文本文件,这个文件 ...
- 乘风破浪:LeetCode真题_027_Remove Element
乘风破浪:LeetCode真题_027_Remove Element 一.前言 这次是从数组中找到一个元素,然后移除该元素的所有结果,并且返回长度. 二.Remove Element 2.1 问题 2 ...
- 读高性能JavaScript编程 第一章
草草的看完第一章,虽然看的是译文也是感觉涨姿势了, 我来总结一下: 由于 大多数浏览器都是 single process 处理 ui updatas and js execute 于是产生问题: js ...
- mysql 错误2203 1061 及安装最后出现2003现象的解决办法
错误描述 : 1.#2003-服务器没有响应MySQL无法启动 2.Can''t connect to MySQL server on ''localhost'' (10061) 3.ERROR 20 ...
- python第三十课--异常(raise关键字)
演示: 1.手动抛出异常对象-->raise关键字 2.try-except代码不能解决语法错误 try: print('try...') raise TypeError('类型有误的异常') ...
- PAT A1004 Counting Leaves (30 分)——树,DFS,BFS
A family hierarchy is usually presented by a pedigree tree. Your job is to count those family member ...
- C内存管理相关内容--取自高质量C++&C编程指南
1.内存分配方式 内存分配方式有三种: (1)从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. (2) 在栈上创建.在执行函数 ...