容器(vector)、数组、new创建的动态数组,你到底用哪一个(执行效率分析)
来源:互联网 发布:新手学java看什么书 编辑:程序博客网 时间:2024/04/29 23:35
1.问题的提出
在没有了解vector之前,动态数组一般都是又new创建的。在了解vector后发现vector竟是那样方便好用,但方便的同时却是以牺牲执行效率为代价的。网上对vector和array的评价和吐槽,也是喜忧参半,各有不同啊。在面临选择的时候,我们到底用哪一种呢,我们可能都犹豫过?下面对该问题进行理论分析和实际测试验证。
2.理论分析
2.1预备知识-程序的内存分配
一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。是一种线性结构,其操作方式类似于数据结构中的栈,操作速度较快。但程序员是无法控制。
2 、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,是一种链式结构,分配方式倒是类似于链表,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
其中栈和堆构成了动态数据区:
├———————┤低端内存区域
│ …… │
├———————┤
│ 动态数据区 │
├———————┤
│ …… │
├———————┤
│ 代码区 │
├———————┤
│ 静态数据区 │
├———————┤
│ …… │
├———————┤高端内存区域
以上堆和栈的分析参考博客1,关于堆和栈的区别与联系更详细的分析,请点击博客1
2.2数组、动态数组和vector的讨论如下:
回到本文的主题,数组是底层数据类型,存放在栈中,其内存的分配和释放完全由系统自动完成,效率最高;动态数组是程序员由new运算符创建的,存放在堆中,需由delete运算符人工释放,否则会内存泄露;vector,存放在堆中,由STL库中程序负责内存的分配和释放,使用方便。
关于vector的分析,参考STL源码剖析(P119-vector的内存管理)和C++primer(第四版9.4vector容器的自增长),vector的构造和内存管理如图1所示。如果容器中已经没有空间容纳新的元素,此时,由于元素必须连续存储以便索引访问,所以不能在内存中随便找个地方存储这个新元素。于是,vector 必须重新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储空间中的元素被复制到新存储空间里,接着插入新元素,最后撤销旧的存储空间。这是vector效率低的主要原因。
注意所谓的动态自增加,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。注意size和capacity的区别,size指容器当前拥有的元素个数,capacity指容器在必须分配新存储空间之前可以存储的元素总数,capacity总是大于或等于size的。
图1(来自STL源码剖析,图4-2)
3.数组、动态数组、vector的测试
对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。总之,数组和容器各有千秋,若硬件速度够快,对时间要求不那么高,用容器方便,也未尝不可。关键看你,看中什么,是效率还是方便。
- 容器(vector)、数组、new创建的动态数组,你到底用哪一个(执行效率分析)
- vector动态二维数组(容器的容器)占用内存分析
- vector动态二维数组(容器的容器)占用内存分析
- vector动态创建数组
- vector动态创建数组
- STL vector 动态数组(容器) 2011.04.14
- vs2010下关于vector和动态数组的效率区别
- C++ 用new 动态创建多维数组
- C++ 用new 动态创建多维数组
- C++ 用new 动态创建多维数组
- C++ 用new 动态创建多维数组
- C++ 用new 动态创建多维数组
- 动态创建二维vector数组
- 动态创建二维vector数组
- 动态创建二维vector数组
- 动态创建二维vector数组
- 动态创建二维vector数组
- 动态创建二维vector数组
- android 之 JNI 详解(四)
- *usaco training 5.4.4 Betsy's Tour 题解
- Fuel4D 2.2 发布
- Construct Binary Tree from Inorder and Postorder Traversal
- hdu 2028 Lowest Common Multiple Plus(最大公约数最小公倍数)(备战LQB)
- 容器(vector)、数组、new创建的动态数组,你到底用哪一个(执行效率分析)
- c# winform combobox追加数据
- android 之 JNI 详解(五)
- linux下安装并开启SSH服务
- 题目1051:数字阶梯求和 2010年哈尔滨工业大学计算机研究生机试真题
- UITabBarController详解(二)UITabBarController的代理方法以及模态显示
- diray6(打印最小数组)
- HDU1598find the most comfortable road(并查集)
- C++标准库:bitset 用法整理