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(0),map_size(0)

            {

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

                

                // 8 缓存区数量+2

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

                

                //分配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) / 2;

                

                

                map_pointer nfinish = nstart + num_nodes -1;

                

                

                //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)

            {

                if( finish.cur != finish.last -1)

                {

                    

                    

                    //使用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 + 1) = allocate_node();

                

                __STL_TRY

                {

                    

                    construct(finish.cur , t_copy);

                    

                    finish.set_node(finish.node + 1);

                    

                    finish.cur = finish.first;

                }

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

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

            }

            

            //push_front

            

            void push_front(const value_type& t)

            {

                if(start.cur != start.first)

                {

                    construct(start.cur-1,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 - 1) = allocate_node();

                

                __STL_TRY

                {

                    start.set_node(start.node - 1);

                    start.cur=start.last - 1;

                    construct(start.cur , t_copy);

                    

                }

                catch(..)

                {

                    start.set_node(start.node + 1);

                    start.cur=start.first;

                    

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

                    deallocate_node(*(start.node - 1));

                }

            }

            

            void reserve_map_at_back (size_type nodes_to_add = 1)

            {

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

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

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

                if(nodes_to_add + 1 > map_size - (finish.node - map))

                    

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

                

            }

            

            void reserve_map_at_front (size_type nodes_to_add = 1)

            {

                

                //同上

                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 + 1;

                

                size_type new_num_nodes = ole_num_nodes + nodes_to_add;

                

                

                map_pointer new_nstart;//T**类型

                

                

                if(map_size > 2 * 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) / 2

                    + (add_at_front ? nodes_to_add : 0);

                    

                    //防止覆盖问题

                    if(new_nstart < start.node)

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

                    else

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

                    

                }

                else

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

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

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

                    

                    

                    map_pointer new_map =map_allocator::allocate(new_map_size);

                    

                    //同上

                    new_nstart = new_map + (new_map_size - new_num_nodes) / 2

                    + (add_at_front ? nodes_to_add : 0);

                    

                    copy(start.node, finish,node +1, 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 - 1);

                finish.cur = finish.last -1;

                destroy(finish.cur);

            }

            

            //pop_front

            

            void pop_front()

            {

                if(start.cur != start.last -1 )

                {

                    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 +1);

                start.cur = start.first;

            }

            

            

            //clear

            template<class T,class Alloc,size_t BufSize>

            void deque<T,Alloc,BufSize>::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)

                {//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;

                if(index < (size() >> 1))

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

                    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;

                    

                    

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

                        setart = new_start;

                    }

                    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;

                    }

                    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;

                if(index < size() / 2)

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

                    

                    //新加一个元素到头部

                    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;

            }

posted @ 2015-03-15 02:00  boydfd  阅读(423)  评论(0编辑  收藏  举报