STL_学习_vector容器源码解析

这里自己总结了自己对SGI的vector容器的操作原理的一点理解。

#ifndef _STL_VECTOR_H_
#define _STL_VECTOR_H_

template<class T, class Alloc=alloc>
class vector{
public:
    typedef T value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type* iterator;
    typedef const value_type* const_iterator;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
protected:
    //定义一个空间配置器,以元素大小为配置单位,也就是value_type类型的大小为配置单位
    typedef simple_alloc<value_type, Alloc> data_allocator;
    //目前使用空间的头
    iterator start;
    //目前使用空间的尾
    iterator finish;
    //目前可用空间的尾
    iterator end_of_storage;
    //负责释放空间
    void deallocate()
    {
        if(start){
            data_allocator::deallocate(start, end_of_storage - start);
        }
    }
    //填充空间并且进行初始化
    void fill_initialize(size_type n, const T& value)
    {
        start = allocate_and_fill(n, value);
        finish = start + n;
        end_of_storage = finish;
    }

    iterator allocate_and_fill(size_type n, const T& x)
    {
        iterator result = data_allocator::allocate(n);
        uninitialized_fill_n(result, n, x);
        return result;
    }

//以下是vector容器提供的相应的接口,这里没有写全
public:
    iterator begin(){return start;}//返回容器的起始位置
    iterator end(){return finish;}//返回容器的结束位置
    size_type size(){return size_type(end() - begin());}//使用空间的大小
   //返回容器的大小
    size_type capacity()const
    {
        return size_type(end_of_storage - begin());
    }
    bool empty()const{return begin() == end();}
    //重载[]就可以进行下标的访问
    reference operator[](size_type n){return *(begin() + n);}
    
public:
    //5个构造函数的重载
    vector():start(0),finish(0),end_of_storage(0){}
    vector(size_type n, const T& value)
    {
        fill_initialize(n, value);
    }
    vector(int n, const T& value){fill_initialize(n, value);}
    vector(long n, const T& value){fill_initialize(n, value);}
    vector(size_type n){fill_initialize(n, T());}

    ~vector()
    {
        destroy(start, finish);
        deallocate();
    }

    reference front(){return *begin();}//返回容器第一个元素的值
    reference back(){return *(end() - 1);}
    //尾插
    void push_back(const T & x)
    {
        if(finish != end_of_storage){
            construct(finish, x);
            ++finish;
        }
        //如果空间不足则调用insert_aux()
        else{
            insert_aux(end(), x);
        }
    }
    //尾删,这里注意尾删只是将最后一个元素删除但是空间并没有释放
    void pop_back()
    {
        --finish;
        destory(finish);
    }
    //删除范围内的元素
    iterator erase(iterator first, iterator last)
    {
        iterator i = copy(last, finish, first);
        destory(i, finish);
        finish = finish - (last - first);
        return first;
    }
    //删除某个位置上的元素(将删除位置后面的元素直接往前移动覆盖掉要删除的元素即可)
    iterator erase(iterator position)
    {
        if(position + 1 != end()){
            copy(position + 1, finish, position);
        }
        --finish;
        destory(finish);
        return position;
    }
    //清空容器
    void clear()
    {
        erase(begin(), end());
    }
    //插入
    void insert(iterator position, size_type n, const T & x);


};

template<class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x)
{
    if(finish != end_of_storage){
        construct(finish, *(finish - 1));
        ++finish;
        T x_copy = x;
        copy_backward(position, finish - 2, finish - 1);
        *position = x_copy;
    }
    //没有空间则扩充空间(申请新的空间大小为旧空间的2倍,拷贝元素到新空间,释放旧空间)
    else{
        const size_type old_size = size();
        const size_type len = old_size != 0?2 * old_size : 1;
        iterator new_start = data_allocator::allocate(len);
        iterator new_finish = new_start;
        new_finish = uninitialzed_copy(start, position, new_start);
        construct(new_finish, x);
        ++new_finish;
        new_finish = uninitialzed_copy(position, finish, new_finish);
        
    }
    destory(begin(), end());
    deallocate();
    start = new_start;
    finish = new_finish;
    end_of_storage = new_start + len;
    
}
//这里的插入操作分为2类
//(1)有足够的空间
//     (1)判断插入的元素个数如果小于插入点之后的元素个数,先确定新的finish,然后再将插入
//          点后面的元素拷贝到old_finish,最后填充要插入的元素
//     (2)插入的元素个数大于等于插入点之后的元素个数,先将要插入的元素的结束位置固定好,
//          然后将插入点以后的元素拷贝到之前固定好的结束位置处,最后填充要插入的元素
//(2)空间不足
template<class T, class Alloc>
void vector<T, Alloc>::insert(iterator position, size_type n, T& x)
{
    if(n != 0){
        if(n < (size_type)(end_of_storage - finish)){
            T x_copy = x;
            const size_type elems_after = finish - position;
            iterator old_finish = finish;
            if(elems_after > n){
               uninitialized_copy(finish - n, finish, finish);
               finish += n;
               copy_backward(position, old_finish - n, old_finish);
               fill(position, position + n, x_copy);
            }
            else{
                uninitialized_fill_n(finish, n - elems_after, x_copy);
                finish += n - elems_after;
                uninitialized_copy(position, old_finish, finish);
                finish += elems_after;
                fill(position, position + n, x_copy);
            }
        }
        else{
            const size_type old_size = size();
            const size_type len = old_size != 0?2*old_size:1;
            iterator new_start = data_allocator::allocate(len);
            iteratoe new_finish = new_start;
            new_finish = uninitialized_copy(start, position, new_start);
            new_finish = uninitialized_fill_n(new_finish, n, x);
            new_finish = uninitialized_copy(position, finish, new_finish);
      
            destory(start, finish);
            deallocate();

            start = new_start;
            finish = new_finish;
            end_of_storage = finish + len;
        }
        
    }
}

#endif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章