zoukankan      html  css  js  c++  java
  • 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;

                }

  • 相关阅读:
    MVC 学习(二)之Linq to Sql 简单Demo
    MVC 学习(一)Linq to Entities 简单Demo
    MVC学习(三)Code-First Demo
    pickle 模块
    json 模块
    sys 模块
    os 模块
    random(随机)模块
    time 模块
    python之函数基础
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983172.html
Copyright © 2011-2022 走看看