STL源码剖析读书笔记之vector

1.vector概述

vector是一种序列式容器,我的理解是vector就像数组。但是数组有一个很大的问题就是当我们分配

一个一定大小的数组的时候,起初也许我们不会觉得数组容量太小不合需求,但是随着数据量的增加,

数组尺寸大小不再满足需求,此时我们需要手动的去扩展其大小。然而vector就帮我们完全实现了一个可

自适应增长的数组功能。那么这样看来vector其实也就是一种可自适应增长的动态数组的类的实现。

2.关于vector的定义

其实用过vector的人都知道 vector的定义大都像这个样子:

 vector<int> v1;
vector<sting> v2;

很显然vector是一种与类型无关的类模板,支持各种类型的vector,这也很好的体现了C++的泛型思想,正

是这种类型无关性,使得STL在各种平台上广为使用。

这里我只是贴出STL源码剖析书中一小部分vector定义

 template <class T,class Alloc=alloc>
class vector
{
public:
typedef T value_type;
typedef valuetype* pointer;
typedef valuetype* iterator;
typedef valuetype& reference;
typedef size_t size_type;
......
protected:
iterator start;
iterator finish;
iterator end_of_storage;
....
pubic:
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());}
reference front {return *begin()}
}

上面有几个关键点:

vector维护了三个迭代器:start,finish和end_of_storage由typedef valuetype* iterator可知迭代器说白

了就是指针。那么vector维护的三个迭代器(指针)的意思是什么呢。start指向vector的第一个元素。finish

指向vector已经使用的空间的最后一个元素的下一个元素。end_of_storage指向vector总共可用空间的最后

一个元素的下一个元素所以操作vector与操作指针完全类似,只是在vector中把这些操作封装成相应的方法

直接供读者使用罢了。

3.vector内存分配原理

不是之前我们说vector是一种自增长的动态数组吗?那么其子增长的原理是什么。

其实很简单:

1.当vector为空时,我们插入一个元素到vector中,这时候vector将内存容量变为1,然后将新的元素插入其中

2.当vector容量为1的时候,此时vector中刚好有一个元素,若要插入一个2,这时候将重新new一个内存为2的新空

间,将之前内存中的1拷贝到新内存并释放1旧内存,同时将新的元素2插入其中

3.重复步骤2,只要就内存容量已满就重新分配新内存,新内存的大小是旧内存的二倍,再讲旧内存中的数据赋

值到新内存,同时释放新内存。同时插入新元素在新的内存空间。

我们可以用下面的程序验证这一点:

 #include <iostream>
#include <vector>
using namespace std; int main(int argc, char* argv[])
{
std::vector<int> v1; cout<<"v1.size()="<<v1.size()<<" "<<"v1.capacity()="<<v1.capacity()<<endl;
v1.push_back();
cout<<"v1.size()="<<v1.size()<<" "<<"v1.capacity()="<<v1.capacity()<<endl;
v1.push_back();
cout<<"v1.size()="<<v1.size()<<" "<<"v1.capacity()="<<v1.capacity()<<endl;
v1.push_back();
cout<<"v1.size()="<<v1.size()<<" "<<"v1.capacity()="<<v1.capacity()<<endl;
v1.push_back();
cout<<"v1.size()="<<v1.size()<<" "<<"v1.capacity()="<<v1.capacity()<<endl;
v1.push_back();
cout<<"v1.size()="<<v1.size()<<" "<<"v1.capacity()="<<v1.capacity()<<endl;
return ;
}

截图如下:

此外,有几个问题需要注意:

1.为什么vector容量满了之后要重新开辟新的内存,因为vector要求连续的内存空间

2.如果重新开启新内存太频繁应该会造成较大的程序开销,怎么办.我们可以一开给reserve一个大的capacity.

3.重新开启新内存是否会造成原来的迭代器失效 ?是的,所以我们最好知道何时会开辟新的capacity,进而防止这种迭代器失效。

4.对于vector删除或者插入造成的迭代器失效已经在之前的博文中有介绍。

STL源码剖析读书笔记之vector的更多相关文章

  1. STL源码剖析读书笔记--第四章--序列式容器

    1.什么是序列式容器?什么是关联式容器? 书上给出的解释是,序列式容器中的元素是可序的(可理解为可以按序索引,不管这个索引是像数组一样的随机索引,还是像链表一样的顺序索引),但是元素值在索引顺序的方向 ...

  2. Stl源码剖析读书笔记之Alloc细节

    阅读基础: Foo *pf = new Foo; 执行了两个步骤: 1)::operator new 向系统申请内存. 2) 调用Foo::Foo()构造函数构造实例.  ==> 申请内存,构造 ...

  3. STL源码剖析读书笔记--第6章&第7章--算法与仿函数

    老实说,这两章内容还蛮多的,但是其实在应用中一点点了解比较好.所以我决定这两张在以后使用过程中零零散散地总结,这个时候就说些基本概念好了.实际上,这两个STL组件都及其重要,我不详述一方面是自己偷懒, ...

  4. STL源码分析读书笔记--第二章--空间配置器(allocator)

    声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...

  5. c++ stl源码剖析学习笔记(一)uninitialized_copy()函数

    template <class InputIterator, class ForwardIterator>inline ForwardIterator uninitialized_copy ...

  6. (原创滴~)STL源码剖析读书总结1——GP和内存管理

    读完侯捷先生的<STL源码剖析>,感觉真如他本人所说的"庖丁解牛,恢恢乎游刃有余",STL底层的实现一览无余,给人一种自己的C++水平又提升了一个level的幻觉,呵呵 ...

  7. 重温《STL源码剖析》笔记 第三章

    源码之前,了无秘密. --侯杰 第三章:迭代器概念与traits编程技法 迭代器是一种smart pointer auto_Ptr 是一个用来包装原生指针(native pointer)的对象,声明狼 ...

  8. 重温《STL源码剖析》笔记 第五章

    源码之前,了无秘密  ——侯杰 序列式容器 关联式容器 array(build in) RB-tree vector set heap   map priority-queue multiset li ...

  9. 重温《STL源码剖析》笔记 第一章

    源码之前,了无秘密. --侯杰 经典的书,确实每看一遍都能重新收获一遍: 第一章:STL简介 STL的设计思维:对象的耦合性极低,复用性极高,符合开发封闭原则的程序库. STL的价值:1.带给我们一套 ...

随机推荐

  1. POJ3630——简单Trie树

    这个题的意思是说,给出一些字符串,判断是否有字符串是另一个字符串的前缀,当然可以用排序水过,不过这个题拿来练习一下Trie树不错. 这个题在poj的discuss上好多人说必须要静态建树,估计都是用了 ...

  2. hdu 4405 Aeroplane chess(概率+dp)

    Problem Description Hzz loves aeroplane chess very much. The chess map contains N+ grids labeled to ...

  3. C#模拟网站用户登录

    我们在写灌水机器人.抓资源机器人和Web网游辅助工具的时候第一步要实现的就是用户登录.那么怎么用C#来模拟一个用户的登录拉?要实现用户的登录,那么首先就必须要了解一般网站中是怎么判断用户是否登录的. ...

  4. mycat实例(2)

    全局序列号 数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯一性标识,这种保证全局性的数据唯一标识的机制就是全局序列号(sequence). 1. 本地 ...

  5. .net批量删除和添加

    往页面上拖一个GridView,设置好数据源,并为GridView添加一个模板列,往模板列里添加一个chekcbox,比如下面的代码 <asp:GridView ID="GridVie ...

  6. 自由缩放属性-resize(禁止textarea的自由缩放尺寸功能)

    resize:none|both|horizontal|vertical|inherit 可以用来改变元素的尺寸大小 用上这个属性后元素的有下脚会有一个小图标 拖它就可以了 但是我把resize:bo ...

  7. Android画一个随意拖动的圆形

    import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactor ...

  8. ios10 适配问题总结

    看各个大神整理而成 1.检查版本问题 不可以像下面这样用 #define isiOS10 ([[[[UIDevice currentDevice] systemVersion] substringTo ...

  9. Object.create函数

    创建一个具有指定原型且可选择性地包含指定属性的对象. Object.create(prototype, descriptors) 参数 prototype必需. 要用作原型的对象. 可为 null. ...

  10. js数组小结

    1.js数组使用sort()排序 var a = ["1","12","3","4","0"]; d ...