SGI STL的序列式容器之vector浅析

vector和array的数据安排和操作方式比较相似, 但是二者又有区别,区别就在于空间运用的灵活性
array是静态空间,配置之后就不能更改,只能重新配置新的空间;
vector是动态空间,加入元素时其内部会自行扩充空间区容纳新元素;vector不存在浪费内存和越界问题,随机访问比较快,但是头部插入和删除比较慢(要进行移动),尾部插入和删除较快;

vector的迭代器类型:Rabdom Access Iterator(随机存取迭代器),vector支持随机存取,普通指针又有此能力,所以用的是普通指针。

vector的应用场景:vector支持随机存取,动态扩张,适合多查询的应用场景,但是,其内存需要保持连续,所以在删除某个元素后,其后续元素需要前移,这样会带来消耗,所以不适合随机删除的场景。

vector实现技术的关键是其对大小的控制以及重新配置时的数据移动效率

vector的数据结构:

vector采用的是数据结构是线性连续空间。用两个迭代器start和finish来指向配置空间中已经使用的空间的头和尾,finish - start的结果就是当前已经使用的空间的大小; 用迭代器end_of_storage表示所配置空间的尾部;则end_of_storahe - finish就是剩余的空间大小, end_of_storage - start就是整块空间的大小;
注意finish指向的是已使用空间的最后一个元素的下一个空间,在得到尾元素的引用时要将迭代器 - 1

template<class T, class Alloc = alloc>  
class vector
{
...
protected:
    iterator start;
    iterator finish; 
    iterator end_of_storage;
...
};

vector使用alloc作为空间配置器,vector还定义了一个data_allocator配置器,目的是为了更方便的以元素大小为单位来配置空间;

vector的空间配置策略:

当利用push_back()在vector尾部插入元素时,push_back()函数
(1)先检查vector是否还有备用空间,如果有就直接在备用空间构造元素,并调整迭代器finish,使得vector变大;
(2)如果没有空间就扩充空间(重新配置空间, 移动数据, 释放原有空间)

 void push_back(const T& x)
   {
       if(finish != end_of_storage){
           //还有备用空间
           construct(finish, x);    //内部采用定位new实现
           ++finish;
       }else{
           //已经没有备用空间
           insert_aux(end(), x);
       }
   }


template<class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x)
{
    if(finish != end_of_storage){
        //还有备用空间
        //在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值
        construct(finish, *(finish - 1));   
        ++finish;
        T x_copy = x;
        copy_backward(position, finish - 2, finish - 1);
        *position = x_copy;
    }else{
        const size_type old_size = size();
        const size_type len = old_size != 0 ? 2 * old_size : 1;
        //若原大小为0,则配置一个元素大小
        //若原大小不为0,则配置原大小的两倍; 前半段用来存放原数据,后半段用来存放新数据
        iterator new_start = data_allocator::allocate(len);   //配置空间
        iterator new_finish = new_start;  //新配置的空间其内还没有元素,所以迭代器的头尾指向相同

        new_finish = uninitialized_copy(start, position, new_start); //将原数据至插入点的元素拷贝至新的vector
        construct(new_finish, x);   //将x插入
        ++new_finish;   //调整迭代器

        new_finish = uninitialized_copy(position, finish, new_finish);  //将原vector中的插入点至finish的元素拷贝至新vector

        //释放原vector
        destroy(begin(), end());   //释放原vector中的元素
        deallocate();    //释放原vector空间

        //调整迭代器,指向新的vector
        start = new_start;
        finis = new_finish;
        end_of_storage = new_start + len;
    }
}

vector的插入操作

template<class T, class Alloc>
void vector<T, Alloc>::insert(iterator position, size_type n, const T& x)
{
    if(n != 0){    //插入元素个数不为0时才插入
        if(size_type(end_of_storage - finish) >= n){    //备用空间>=要插入的元素个数
            T x_copy = x;
            const size_type elems_after = finish - position;  //得到插入点之后的元素个数
            iterator old_finish = finish;
            if(elems_after > n){   //插入点后的现有元素个数>n
                //将finish前的n个元素后移至finish后
                uninitialized_copy(finish - n, finish, finish);
                finish += n; //调整迭代器(后移)
                //将插入点至finish-n之间的元素后移至旧finish之前
                copy_backward(position, old_finish - n, old_finish);
                //将新元素插入至position至position+n之间的位置
                fill(position, position + n, x_copy);
            }else{   //插入点后的元素个数<= n
                //先在finish后插入n - elems_after(finish前可插入的元素的剩余个数)个元素
                uninitialized_fill_n(finish, n - elems_after, x_copy);
                finish += n - elems_after;   //调整迭代器
                //再将插入点至旧的finish之间的元素后移至新的finish后
                uninitialized_copy(position, old_finish, finish);
                finish += elems_after;  //调整迭代器
                //最后将x_copy插入position至旧的finish之间的位置
                fill(position, old_finish, x_copy);         
            }
        }else{   //备用空间的元素个数<= n
        //(1) 确定新的空间长度,旧长度的两倍或者是旧长度+新曾的元素个数
        const size_type old_size = size();    //得到旧的长度
        const size_type len = old_size + max(old_size, n);   //确定新的长度

        //(2 )配置新的vector空间
        iterator new_start = data_allocator::allocate(len);
        iterator new_finish = new_start;

        //(3) 将旧vector的插入点之前的元素插入(复制到)新的vector空间
        new_finish = uninitialized_copy(start, position, new_start);
        //(4) 将新增的元素插入new_finish后
        new_finish = uninitialized_fill_n(new_finish, n, x);
        //(5) 将旧vector空间的position后至finish间的元素插入新的vector的new_finish后的空间
        new_finish = uninitialized_copy(position, finish, new_finish);

        //(6) 清除旧的元素并释放旧vector的空间
        destroy(start, finish);
        deallocate();

        //(7) 调整新的迭代器标记
        start = new_start;
        finish = new_finish;
        end_of_storage = new_start + len;
        }
    }
}

vector的删除操作:

//尾部删除
   void pop_back()
   {
       --finish;
       destroy(finish);
   }
   //删除某个位置上的元素
   iterator erase(iterator position)
   {
       if(position + 1 != end()){
           //copy从前向后拷贝,即*position = *(position + 1),直到拷贝至finish - 1位置结束,返回一个迭代器position + (finish - (position + 1))
           copy(position + 1, finish, position); 
       }
       --finish;   //调整迭代器
       destroy(finish);   //释放最后一个元素
       return position;  //返回要删除的位置
   }

   //删除某个范围内的元素
   iterator erase(iterator first, iterator last)
   {
       //将last后的所有元素前移,返回一个first + (finish - last)的迭代器
       iterator i = copy(last, finish, first);   
       destroy(i, finish);  //释放c从i至finish之间的所有元素
       finish = finish - (last - first);   //调整迭代器
       return first;    //返回要删除的起始位置
   }

调整容器大小的操作

 //增加或删除元素使被控序列的长度变为new_size长
   void resize(size_type new_size, const T& x)    //添加值为x的元素
   {
       if(new_size < size()){   //缩短被控序列(vector)的长度
           erase(begin() + new_size, end());    //删除new_size长度后至end()的元素
       }else{  //增加被控序列的长度
           insert(end(), new_size - size(), x);  //在end()后插入new_size - size()个元素x,使序列长度变为new_size长
       }

   }

   void resize(size_type new_size)   //使被控序列的长度变为new_size
   {
       resize(new_size, T());    //添加值为T()的元素
   }

清空容器

  //清空vector序列
   void clear()
   {
       erase(begin(), end());
   }

vector容器的其他操作

iterator begin()  //的到头迭代器
    {
        return start;
    }
    iterator end()   //得到尾迭代器
    {
        return finish;
    }

    size_type size()const   //求元素个数
    {
        return size_type(end() - begin());
    }
    size_type capacity()const   //求容量
    {
        return size_type(end_of_storage - begin());
    }

    bool empty()const  //判空
    {
        return begin() == end();
    }


    referance operator[](size_type n)   //重载[],得到第n个元素
    {
        return *(begin() + n);
    }
    reference front()   //得到首元素的引用
    {
        return *begin();
    }
    reference back()  //得到末尾元素的引用
    {
        return *(end() - 1);
    }

vector的析构操作

    ~vector()
    {
        destroy(start, finish);   //删除所有元素
        deallocate();     //释放空间
    }

    //释放vector空间
    void deallocate()
    {
        if(start){
            data_allocator::dedallocate(start, end_of_storage - start);
        }
    }

你可能感兴趣的:(vector,迭代器,STL,容器,SGI)