iOS移动端
记得之前做iOS移动端时,关于垃圾回收机制是这样说的:
ARC的基本概念:
ARC(AutoRefrenceCount)自动引用计数,当你在编译程序时提供自动管理内存的功能,它会自动加入内存的控制代码,控制对象的生命周期。这是在iOS4以后引入的技术。此时你在代码中使用release,retain时就会报错,也就是这些方法被禁用。当然你也可以在项目中进行设置,选择重新启用MRC(手动内存管理)。在Build Setting里面把“Objective-C Automatic Reference Counting”设置为NO,就可以不启用ARC。
垃圾回收机制的基本概念:
与Java、.net语言相同,Objective-C2.0以后,也提供了垃圾回收机制。但在iOS移动终端设备中,并不支持垃圾回收机制(取决于终端设备的性能)。因此,iPhone并不能对内存进行自动垃圾回收机制(取决于终端设备的性能)。因此,iPhone并不能对内存进行自动垃圾回收处理(中间模式autorelease)。我们需要注意垃圾回收机制并不是ARC,ARC也是需要管理内存的,只不过是隐式的管理内存,编译器会在适当的地方自动插入retain,release和autorelease.
回到正题
C++ Vector中内存分配和回收机制
1.内存增长
vector所有的内存相关问题都可以归结于它的内存增长策略。vector有一个特点就是:内存空间只会增长不会减少。vector有两个函数,一个是capacity(),返回对象缓冲区(vector维护的内存空间)实际申请的空间大小,另一个size(),返回当前对象缓冲区存储数据的个数。对于vector来说,capacity是永远大于等于size的,但capacity和size相等时,vector就会扩容,capacity变大。
比如说vector最常用的push_back操作,它的整个过程是怎么一个机制呢?这个问题经常在面试中出现。
这个问题其实很简单,在调用 push_back时,若当前容量已经不能够放入新的元素(capacity=size),那么vector会重新申请一块内存,把之前的内存里的元素拷贝到新的内存当中,然后把push_back的元素拷贝到新的内存中,最后要析构原有的vector并释放原有的内存。所以说这个过程的效率是极低的,为了避免频繁的分配内存,C++每次申请内存都会成倍的增长,例如之前是4,那么重新申请后就是8,以此类推。当然不一定是成倍增长,比如在我的编译器环境下实测是0.5倍增长,之前是4,重新申请后就是6。2. 内存释放
就像前面所说的,vector的内存空间是只增加不减少的,我们常用的操作clear()和erase(),实际上只是减少了size(),清除了数据,并不会减少capacity,所以内存空间没有减少。那么如何释放内存空间呢,正确的做法是swap()操作。
标准模板如下
- template < class T >
- void ClearVector( vector< T >& vt )
- {
- vector< T > vtTemp;
- veTemp.swap( vt );
- }
- vector<Point>().swap(pointVec); //或者pointVec.swap(vector<Point> ())
- std::vector<T>().swap(X)
- 作用相当于:
- {
- std::vector<T> temp(X);
- temp.swap(X);
- }
交换之后,temp会被析构。
3.总结
由上可见,vector虽然是动态数组,但是本质上和数组没什么区别,频繁的销毁新建,效率很低,所以正确的做法是新建vector的时候初始化一个合适的大小(笑),回到了数组的老路上。不过之后可以动态变化还是很方便,而且还有很多好用的函数。
vecotr是动态数组,顾名思义他可以动态的增加自己的长度。
内存机制:
但是怎样的增加自己的长度?
vector有两个函数一个是capacity()返回内存空间即缓冲区的大小,另一个是size()返回当前数组中数的数量。vector增加元素来说,当容量已经不能放进数据了,那么他会重新申请一块内存,把之前的内存利用复制构造函数复制到新的内存当中,然后把新添加的内容放入后面,另外此时的他申请的内存空间是原来空间的2倍,我测得是2倍
参考文章:http://www.cnblogs.com/zhaopAC/p/5404828.html
缓冲区的释放
vecotor占用的内存只增不减,erase只是将一段区间( earse(arr.begin(), arr.end() )的值清除掉或者将某个值( erase(x) )清除掉,但是对于内存空间来说是没变化的
所有内存空间是在vector析构时候才能被系统回收。empty()用来检测容器是否为空的,clear()可以清空所有元素。但是即使clear(),vector所占用的内存空间依然如故,无法保证内存的回收。
方法一: vecotr<Type>().swap(arr) // 回收arr内存 方法二: 模板: Template < class T > void ClearVector( vector< T >& vt ) { vector< T > vtTemp; veTemp.swap( vt ); } 调用模板函数 void ClearVector<vector< T> & vt) { vector<int> temp;//临时对象未初始化,其缓冲区大小为0,没有数据 arr.swap(temp);//与我们的对象交换数据,arr的缓冲区就没了。 }//临时变量会被析构,temp调用vector析构函数释放空间
----------------------------------------------------------------------------
性能分析:
主要比较三种插入方式:
1、直接push_back() 2、 reserve(n) 预定n个空间,当然后续push_back()会增加,其中的值不确定, 3 resize(n, x) 申请n个空间初始化为x,
reserve只是保持一个最小的空间大小,而resize则是对缓冲区进行重新分配,里面涉及到的判断和内存处理比较多所以比reserve慢一些,对于数据数目可以确定的时候,先预设空间大小是很有必要的。直接push_back数据频繁移动很是耗时