Vector(动态数组)

vector是动态空间,内存空间是连续的。

template<class T, class Alloc = alloc>
class vector{
public:
    typedef T value_type;
    typedef value_type* pointer;
    typedef value_type* iterator;          //定义迭代器,原生指针做迭代器,因为vector的内存空间是连续的
    typedef value_type& reference;
    typedef size_t size_type;       //尺寸类型
    typedef ptrdiff_t difference_type;

protected:

    typedef simple_alloc<value_type, Alloc> data_allocator;

    iterator start;      //表示目前使用的头
    iterator finish;     //表示目前使用空间的尾
    iterator end_of_storage;   //表示目前可用空间的尾

    void insert_aux(iterator position, const T& x);

    void deallocate(){     //释放内存
      if(start){
          data_allocator::deallocate(start, end_od_storage - start);
      }
    }

    void fill_initialize(size_type n, const T& value){  //填充元素
        start = allocate_and_fill(n, value);
        finish = start + n;           //初始化时finish和end_of_storage一致,也就是说capacity和size相等
        end_of_storage = finish;
    }

public:
    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(); }
    reference operator[](size_type n) { return *(begin() + n); }   //重载[]运算符,返回值为真实值的引用

    //构造函数
    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); }
    explicit vector(size_type n) { fill_initialize(n, T()); }    //禁止隐式转换

    ~vector(){
        destory(start, finish);            //调用对象析构函数
        deallocate();           //释放内存
    }
    reference front() {    //返回第一个元素
        return *begin();
    }
     reference back() {      //返回最后一个元素
        return *(end() - 1);
    }
    void insert(iterator position, size_type n, const T& x);    //在迭代器的某个位置插入一个元素
    void push_back(const T& x){
        if(finish != end_of_storage){   //vector还有足够的空间
            construct(finish, x);
            ++finish;
        }else{                 //没有足够的空间
            insert_aux(end(), x);     //扩充空间
        }
    }
    void pop_back(){
        --finish;
        destroy(finish);     //析构该对象,vector的内存保留
    }


    iterator erase(iterator position){    //清除某位置上的元素
       if(position + 1 != end()){
           copy(position + 1, finish, position);   //所有元素前移一位
       }
       --finish;
       destroy(finish);
       return position;
    }
    void resize(size_type new_size, const T &x){
        if(new_size < size()){
            erase(begin() + new_size, end());
        }else {
            insert(end(), new_size - size(), x);
        }
    }
    void resize(size_type new_size) {  resize(new_size, T()); }
    void clear() { erase(begin(), end()); }

protected:
    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实际制的大小可能比客户端需求量大一些,以备将来可能的扩充。这就是容量的概念。也就是end_of_storage的意义。

template<class T, class Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x){    //push_backinsert都可能会调用该函数
    if(finish != end_of_storage){                
        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 ? old_size * 2 : 1;  //申请两倍之前的空间大小

        iterator new_start = data_allocator::allocate(len);    //分配内存
        iterator new_finish = new_start;
        try{
            new_finish = uninitialized_copy(start, position, new_start);   //复制原来的元素到新的内存空间
            construct(new_finish, x);
            ++new_finish;
            new_finish = uninitialized_copy(position, finish, new_finish);   //position之后的元素也移到新的内存中
        }catch(...){
            destory(new_start, new_finish);    
            data_allocator::deallocate(new_start, len);
            throw;
        }
        destory(begin(), end());
        deallocate();

        start = new_start;     //调整迭代器,指向新的vector内存
        finish = new_finish;
        end_of_storage = new_start + len;   //end_of_storage和finish开始不一样
    }

}     
template<class T, class Alloc>
void vector<T, Alloc>::insert(iterator position, size_type n, const T& x){
    if(n != 0){
        if(size_type(end_of_storage - finish) >= n){   //备用空间大于新增元素个数
            T x_copy = x;
            const size_type elems_after = finish - position;
            iterator old_finish = finish;
            //不用使用额外的空间,把元素后移n个位置
            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, old_finish, x_copy);
            }
        }
        else{
            const size_type old_size = size();
            const size_type len = old_size + max(old_size,n);

            iterator new_start = data_allocator::allocate(len);  
            iterator new_finish = new_start;
            __STL_TRY {
                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);
            }
#ifdef __STL_USE_EXCEPTIONS
            catch(...){
                destory(new_start, new_finish);
                data_allocator::deallocate(new_start, len);
                throw;
            }
#endif
            destory(begin(), end());
            deallocate();

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

对于vector来说,它的重点在于内存的申请,因为vector是一个动态数组。

image-20231129153738422

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top