STL源码解析(vector)

vector的数据结构

template 
class vector {
...
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); }
    reference front() { return *begin(); }
    reference back() { return *(end() - 1); }
...
protected:
    iterator start;             //表示目前使用空间的头
    iterator finish;            //表示目前使用空间的尾
    iterator end_of_storage;    //表示目前可用空间的尾
...
}

vector 有 size(), capacity(), resize(), reserve() 这几个和大小, 容量相关的接口
size() 表示 vector 的大小(已用空间大小);
resize() 表示改变 vector 的大小(已用空间大小);
capacity() 表示 vector 的容量(总大小);
reserve() 表示改变 vector 的容量(总大小);
capacity() - size() 表示 vector 剩余可用空间的大小. vector 的容量永远大于或等于其大小. 当 capacity() = size() 时, 表示已经没有剩余空间, 下次增加数据会引起vector空间的动态增长。


vector容量增长.png

vector内存管理

void push_back(const T& x)
{
    if (finish != end_of_storage)   //还有备用空间
    {
        construct(finish, x);       //全局函数
        ++finish;                   //调整finish
    }
    else                            //无备用空间
    {
        insert_aux(end(), x);       //vector member function
    }
}

template 
void vector::insert_aux(iterator position, const T& x)
{
    if (finish = != end_of_storage)         // 还有备用空间
    {
        construct(finish, *(finish - 1));   // 在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值
        ++finish;                           // 调整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 * ols_size : 1;
        // 以上配置原则,如果原大小为0,则配置1(个元素)
        // 如果原大小不为0,则配置原大小的两倍
        // 前半段用来放置源数据,后半段准备用来放置新数据

        iterator new_start = data_allocator::allocate(len); // 实际配置
        iterator new_finish = new_start;
        try {
            // 将原 vector 的内容拷贝到新的 vector
            // uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result);
            // 迭代器 first 指向输入端的起始位置, 迭代器 last 指向输入端的结束位置(前闭后开区间)
            // 迭代器 result 指向输出端(欲初始化空间)的起始位置
            new_finish = uninitialized_copy(start, position, new_start);
            // 为新元素设定初值x
            construct(new_finish, x);
            // 调整finish
            ++new_finish;
            // 将安插点的原内容也拷贝过来
            new_finish = uninitialized_copy(position, finish, new_finish);
        }
        catch (...) {
            destroy(new_start, new_finish);
            data_allocator::deallocate(new_start, len);
            throw;
        }

        // 析构并释放原 vector
        destory(begin(), end());
        deallocate();

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

动态扩容是只分配一个原来大小两倍的新空间, 然后将源数据拷贝到新空间, 再在新空间构造新元素, 最后是否原空间
由于动态扩容涉及到新内存的分配, 源数据的拷贝以及原内存的释放, 这一系列操作对性能影响较大, 为了预防动态扩容, 如果预先知道要添加元素的数量, 可以先对vector做 reserve() 操作, 将 vector 的容量设置成需要的大小

你可能感兴趣的:(STL源码解析(vector))