在没有了解vector以前,动态数组通常都是又new建立的。在了解vector后发现vector竟是那样方便好用,但方便的同时倒是以牺牲执行效率为代价的。网上对vector和array的评价和吐槽,也是喜忧参半,各有不一样啊。在面临选择的时候,咱们到底用哪种呢,咱们可能都犹豫过?下面对该问题进行理论分析和实际测试验证。程序员
一个由C/C++编译的程序占用的内存分为如下几个部分
一、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。是一种线性结构,其操做方式相似于数据结构中的栈,操做速度较快。但程序员是没法控制。
2 、堆区(heap) — 通常由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,是一种链式结构,分配方式却是相似于链表,通常速度比较慢,并且容易产生内存碎片,不过用起来最方便。
三、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另外一块区域。 - 程序结束后有系统释放
四、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放
五、程序代码区—存放函数体的二进制代码。数组
其中栈和堆构成了动态数据区:数据结构
├———————┤低端内存区域
│ …… │
├———————┤
│ 动态数据区 │
├———————┤
│ …… │
├———————┤
│ 代码区 │
├———————┤
│ 静态数据区 │
├———————┤
│ …… │
├———————┤高端内存区域
函数
以上堆和栈的分析参考博客1,关于堆和栈的区别与联系更详细的分析,请点击博客1测试
回到本文的主题,数组是底层数据类型,存放在栈中,其内存的分配和释放彻底由系统自动完成,效率最高;动态数组是程序员由new运算符建立的,存放在堆中,需由delete运算符人工释放,不然会内存泄露;vector,存放在堆中,由STL库中程序负责内存的分配和释放,使用方便。spa
关于vector的分析,参考STL源码剖析(P119-vector的内存管理)和C++primer(第四版9.4vector容器的自增加),vector的构造和内存管理如图1所示。若是容器中已经没有空间容纳新的元素,此时,因为元素必须连续存储以便索引访问,因此不能在内存中随便找个地方存储这个新元素。因而,vector 必须从新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储空间中的元素被复制到新存储空间里,接着插入新元素,最后撤销旧的存储空间。这是vector效率低的主要缘由。code
注意所谓的动态自增长,并非在原空间以后接续新空间(由于没法保证原空间以后尚有可供配置的空间),而是以原大小的两倍另外配置一块大空间,而后将原内容拷贝过来,而后才开始在原内容以后构造新元素,并释放原空间。所以,对vector的任何操做,一旦引发空间从新配置,指向原vector的全部迭代器就都失效了。注意size和capacity的区别,size指容器当前拥有的元素个数,capacity指容器在必须分配新存储空间以前能够存储的元素总数,capacity老是大于或等于size的。blog
图1(来自STL源码剖析,图4-2)排序
对vector、预先reverse的vector、数组、new建立的动态数组测试代码以下:索引
vector的测试代码:
DWORD start=GetTickCount(); int t=100; int n=200000; while (t) { vector<int> a,b; for (int i=0;i<n;i++) a.push_back(i); t--; } cout<<"Runing time of program:"<<GetTickCount()-start<<endl;
预先reverse的vector的测试代码:
start=GetTickCount(); t=100; n=200000; while (t) { vector<int> a,b; b.reserve(n+1); for (int i=0;i<n;i++) b.push_back(i); t--; } cout<<"Runing time of program:"<<GetTickCount()-start<<endl;
数组的测试代码:
start=GetTickCount(); t=100; n=200000; while (t) { int a[200000]; for (int i=0;i<n;i++) a[i]=i; t--; } cout<<"Runing time of program:"<<GetTickCount()-start<<endl;
new建立的动态数组:
start=GetTickCount(); t=100; n=200000; while (t) { int *p=new int[n+1]; for (int i=0;i<n;i++) p[i]=i; delete []p; t--; } cout<<"Runing time of program:"<<GetTickCount()-start<<endl;
运行结果为:
运行结果从上到下依次为,vector,预先reverse的vector、数组和动态数组的以上代码的执行时间(单位ms),从中能够看出,数组的执行效率是vector的10倍左右。执行效率不在同一个数量级,虽然容器操做简单方便。其效率排序依次是数组>动态数组>预先reverse的vector>vector。总之,数组和容器各有千秋,若硬件速度够快,对时间要求不那么高,用容器方便,也何尝不可。关键看你,看中什么,是效率仍是方便。