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

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