• STL源码之vector


    STL源码之vector

     

    1. SGI的vector

    SGI stl vector继承子一个基类:

    template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
        class vector : protected _Vector_base<_Tp, _Alloc>

    在基类中定义了基本的一些操作,并且封装了了vector所需要的基本的三个指针:

    struct _Vector_impl
          : public _Tp_alloc_type
          {
        pointer _M_start;
        pointer _M_finish;
        pointer _M_end_of_storage;

         …

    }

    public:
          _Vector_impl _M_impl;

    以_M_impl作为数据成员。

    现在我们只在一个类中表达出相同含义。

    2. vector基本含义

    #include <memory>
     
     template <typename T, typename Alloc = std::allocator<T> >
     class vector
     {
     public:
        //必须的嵌套类型,必须包含iterator_traits中五个类型
        typedef T                                        value_type;
        typedef value_type*                               pointer;
        typedef const value_type*                         const_pointer;
        typedef value_type&                             reference;
        typedef const value_type&                       const_reference;
        typedef value_type*                            iterator;
        typedef const value_type*                       const_iterator;
        typedef std::reverse_iterator<const_iterator>  const_reverse_iterator;
        typedef std::reverse_iterator<iterator>        reverse_iterator;
        typedef size_t                                    size_type;
        typedef ptrdiff_t                                difference_type;
        typedef Alloc                                  allocator_type;    
    protect:
        iterator start;                //目前使用空间的头:beginn()
        iterator finish;            //目前使用空间尾:end()
        iterator end_of_storage;    //目前可用空间的尾:capacity()
        
        //分配内存时,实际分配的类型。
        //对于vector,值类型是T,实际分配的类型也是T,other 就是 Alloc<T>
        //但是对于其它一些类型就不一定了。
        //比如:list的值类型为T,实际分配的类型是其list_node<T>类型。
        typedef typename template rebind<T>::other T_alloc_type;
        
         T_alloc_type& 
         get_T_allocator() noexcept()
          { return *start; }
    
          const T_alloc_type&
          get_T_allocator() const noexcept()
          { return *start; }
    
          allocator_type
          get_allocator() const noexcept()
          { return allocator_type(get_T_allocator()); }
          
          pointer
          _M_allocate(size_t __n)
          {
        typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
        return __n != 0 ? _Tr::allocate(_M_impl, __n) : 0;
          }
    
          void
          _M_deallocate(pointer __p, size_t __n)
          {
        typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
        if (__p)
          _Tr::deallocate(_M_impl, __p, __n);
          }
        
        //主要的构造函数和复制控制函数
         vector():start(0), finish(0), end_of_storage(0) {}
               
         vector(size_type n, const T& value)
        { 
            fill_initialize(n, value); 
        }
        
         explicit vector(size_type n)
        { 
            default_initialize(n); 
        }
        
        vector(const vector& x)
        { 
            create_storage(n);
            this->finish = std::uninitialized_copy(x.begin(), x.end(), this->start);
        }
         b
    private:
        create_storage(size_t n)
        {
            this->start = Alloc.allocate(n);
            this->finish = this->start;
            this->end_of_storage = this->start + n;
            
        }
        void fill_initialize(size_type n, const value_type& value)
        {
            create_storage(n);
            
            std::uninitialized_fill_n(start, n, value);
            this->finish = this->storage;
        }
        
        #if __cplusplus >= 201103L
          // Called by the vector(n) constructor.
         void default_initialize(size_type n)
        {
            create_storage(n);
            
            std::uninitialized_default_n(start, n);
            this->finish = end_of_storage;
        }
    #endif
    }

    3.构造函数基本的要点
    (1) vector<T> vec; //默认构造函数使start = finish = end_of_storage = 0;
    (2) vector<T> vec(10); //构造10个T()的元素,finish = end_of_storage = start + 10;
    capacity()与size()相同。
    (3) vector<T> vec(10, value); //构造10个值为value的元素,finish = end_of_storage = start + 10;
    capacity()与size()相同。
    (4) vector<T> vec(vec2); //vec的容量与大小相同

    4. 插入的特点
    (1)insert(position, value);
    if (finish != end_of_storage) { //剩余空间足够:直接构造元素,调整finish。
    //在finish构造元素,值为最后一个元素值
    construct(finish, *(finish -1 ));
    ++finish;
    T x_copy = x;
    //把postion到最后一个元素之前的元素向后插入到最后位置
    copy_backward(position, finsish - 2, finish - 1);
    *posion = x_copy;
    } else { //没有剩余空间
    //size()扩大两倍(VS增加大小的一半).原本为0,则size() = 1; capacity = 1;
    //将vector中start..position中元素拷贝到新空间
    //在position构造元素
    //在把之后的元素复制到新空间中

    //释放原本空间
    destroy(begin(), end());
    deallocate();


    (2) insert(position, n, value);
    if (n != 0) {
    if (备用空间 >= n) {
    if (positionz之后元素 > n) {
    先把尾部前的n个元素移到后面
    把position后剩余元素向后复制到尾部前
    填充n个新值
    } else {
    现在尾部fill元素少的元素
    调整finish
    把元素复制到新尾部
    fill剩余的元素
    }
    } else {
    //size()扩大两倍或者原本长度 + n
    //将vector中start..position中元素拷贝到新空间
    //在position构造n个元素
    //在把之后的元素复制到新空间中

    //释放原本空间
    destroy(begin(), end());
    deallocate();
    }
    }

    总结:一旦剩余空间不够,就需要扩充空间,复制元素,释放原空间。所以可以事先确定好大小或者容量。

    5. 关于大小和容量
    (1) resize(n)时,n >= size()使用默认构造初始化多的元素。n < size()截断元素。
    (2) vector<T> vec;
    vec.reserve(n); //start = finish = 0; end_of_storage = start + n;
    容器中没有元素,此时可以vec[i],但是finish不会改变,即size()还是==0;
    此时要想正确的改变size(),必须使用push_back()或者insert()。

    整体行为就是,若n > 现有容量,扩大容量。把旧元素复制到新的空间,然后释放原空间。否则,忽略。
    (3) erase(position); erase(first, last);时:将后面元素复制到erase的位置(就是直接覆盖),
    只是改变了size()。元素capacity()没有改变。
    clear()是同样的情景,clear() = earse(begin(), end());
    (4) 一般情况下容量从不改变,改变的只是size()。
    shrink_to_fit()可以压缩容量的函数。
    ~vector(); //可以释放空间,size() = capacity() = 0;




  • 相关阅读:
    centOS 6 服务管理与服务脚本
    centOS 6启动流程
    shell脚本之流程控制
    centOS7网络配置(nmcli,bonding,网络组)
    模拟主机跨路由通信实验
    网络配置之基本网络配置(cenos6)
    网络基础之IP地址与子网划分
    网络基础之网络层
    我的BO之数据保护
    我的BO之强类型
  • 原文地址:https://www.cnblogs.com/hancm/p/3840425.html
Copyright © 2020-2023  润新知