STL源码解析(vector)

vector的数据结构

template <class T, class Alloc = alloc>
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 <class T, class Alloc>
void vector<T, Alloc>::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 的容量设置成需要的大小

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容