C++Vector源码解析(侯捷STL)

vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新的元素。vector的实现技术,关键在于对大小的控制以及重新配置时的数据移动效率。

一、vector的数据结构

vector采用线性连续空间,以两个迭代器start和finish分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器end_of_storage指向整块连续空间(含备用空间)的尾端。

template<class T, class Alloc = alloc>
class vector{
    ...
protected:
    iterator start;                  //表示目前使用的空间的头
    iterator finish;                 //表示目前使用的空间的尾
    iterator end_of_storage;    //表示目前可用的空间的尾
...
};

二、构造函数

三、属性获取

这⾥需要注意的是因为 end() 返回的是 finish,⽽ finish 是指向最后⼀个元素的后⼀个位置的指针

iterator begin(){return start;}
iterator end(){return finish;}
size_type size()
const {end() - begin();} size_type capacity() const() {end_of_storage() - begin();} bool empty() const {return begin() == end();} reference operator[](size_type n){return *(begin() + n);} reference front() {return *begin();}; reference back() {return * (end()-1);}

四、push_back 操作

  当调⽤ push_back 插⼊新元素的时候,⾸先会检查是否有备⽤空间,如果有就直接在备⽤空间上构造元素,并调整迭代器 finish

void push_back(const T& x){
  //内存满足条件直接追加元素,否则需要重新分配内存
    if (finish != end_of_storage){
        construct(finish, x);
        ++finish;
    }
    else
        insert_aux(end(), x);  // 没有备用空间
}

  construct函数

// <memory> -> <stl_construct.h>
#include<new.h>
template<class T1, class T2>
inline void construct (T1 *p, const T2 &value) {
     new(p) T1(value);
}

  内存扩充操作

无备用空间:如果原空间⼤⼩为 0 则分配 1 个元素,如果⼤于 0 则分配原空间两倍的新空间,然后把数据拷⻉过去

template<class T, class Alloc>
void vector<T,Alloc>::insert_aux(iterator position, const T& x){
    if (finish != end_of_storage){  //又判断一次(因为 insert_aux 函数可能还被其他函数调⽤)
        construct(finish, *(finish-1));  //在备用空间起始处构造一个元素,并以vector中最后一个元素为初始值
        ++finish;

        T x_copy = x;
        copy_backward(position, finish-2, finish-1);  //全局函数,将[first, last)中元素从 pos 从后往前拷贝
        *position =  x_copy;
    }
    else{    //已无备用空间
        const size_type old_size = size();
        const size_type len = old_size != 0 ?2*old_size : 1;
     //old_size开始为0,分配空间1,old_size不为0,扩充为原来的两倍
    
//分配器分配内存 iterator new_start = data_allocator::allocate(len); iterator new_finish = new_start; //内存拷贝 try{ new_finish = uninitialized_copy(start, position, new_start);
//将原vector内容拷贝到新vector内容
            construct(finish, x);
            ++new_finish;    //调整finish位置

            //插入点后面的元素也要拷贝过来
            new_finish = uninitialized_copy(position, finish, new_finish); //拷贝当前后面元素
        } catch(...){
            destroy(new_start, new_finish);
            data_allocator::deallocate(new_start, len);
            throw;
        }

        //释放原内存
        destroy(begin(), end());
        deallocate();

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

 五、pop元素

public:
 //将尾端元素拿掉 并调整⼤⼩
 void pop_back() {
   --finish;//将尾端标记往前移动⼀个位置 放弃尾端元素
   destroy(finish);
 }

六、erase删除元素

erase 函数清除指定位置的元素, 其᯿载函数⽤于清除⼀个范围内的所有元素。实际实现就是 将删除元素后⾯所有元素往前移动

posted @ 2022-04-24 15:33  晚安地球人1  阅读(1736)  评论(0)    收藏  举报