C++内存动态分配及管理
2010-12-11 22:00
465 查看
C++内存动态分配及管理
内存动态分配与管理是C++灵活性的一种体现,本贴探讨C++中内存的动态分配与管理。
一、简单的内存分配
在C++中,引入了一对新的操作符new/delete来动态分配和释放内存。虽然旧的malloc/free仍然有效,但强烈建议不再使用它们。因为new/delete做了一些“我们不知道”的事情。比如有一个类A,我们执行下面的操作:
C++中总是先分配内存,然后调用A的构造函数。那么对应的操作可能是下面的样子:
现在我们知道:malloc/free只是简单的执行内存分配,而new/delete在分配内存的同时,还在这片内存上执行了对象的构造或析构。
二、多维数组的动态分配
有时候我们需要动态分配一个多维数组——比如创建一幅游戏地图。那么我们可以通过动态创建来完成。多维数组的分配有多种方式,如下:
1> 直接分配:
我们用二维数组为例,这个比较容易,如下:
这样就创建了一个三行四列的二维数组,释放操作如下:
也可以像下面操作,比较直观:
这样也创建了一个三行四列的二维数组,释放操作和上面一样。三维、多维的操作和二维的类似。
2> 多次分配:
我们也可以通过多重分配来模拟:
这样也创建了一个三行四列的二维数组,释放操作如下:
可以看出,创建、释放操作比第一种方法麻烦了不少。其余的操作基本一样。所以我们最好用第一种方式来动态创建多维数组。
三、几种new方法:
1> plain new:
这种普通的new方法我们只能通过异常检测来判断内存分配是否成功,而不是通过检测new返回的指针是否为NULL。因为C++标准规定:“plain new在分配失败后抛出std::bad_alloc异常,而不是返回NULL。”示例如下:
像下面的检测操作是无用的:
2> nothrow new:
我们可以通过nothrow来分配一片内存,这样如果分配失败,则返回NULL而不是抛出std::bad_alloc异常:
我们可以知道,哑元nothrow是C++中全局的一个nothrow_t的const对象。
3> placement new:
如果我们频繁动态创建/释放对象,那么我们可能会用到placement new方法,这种方法通过指定一片已动态分配的内存,来在上面执行对象创建操作,而不会重新分配内存。如下:
placement new操作只是简单的在pInterger所指向的内存上执行对象的构造。需要注意的是:placement new分配的内存需要我们自己显式调用析构函数,如:pObj->~ClassName();。
这种方法很有用,比如在一个太空游戏中要动态创建/释放很多的敌机、飞船,那么我们会用到placement new,将分配后要释放的内存简单的放到我们管理的内存池中,然后在下次有对象创建时简单的执行placement new即可。比如我们的内存池为CMemoryPool:
如果我们要创建飞船,那么在需要创建时只需在内存池中查询,如果有可用的内存,则返回一片可用内存并在上面执行placement构造,否则只是创建一份即可。
在飞船被击毁时,只需将它解除,然后添加到内存池即可:
这样就避免了频繁的创建/释放操作使堆千疮百孔了。综上我们简单介绍了C++中动态分配内存的管理等问题。
--By:YaFengZhang
--Date:2010.12.11
--Blog:http://blog.csdn.net/ZhangYafengCPP
内存动态分配与管理是C++灵活性的一种体现,本贴探讨C++中内存的动态分配与管理。
一、简单的内存分配
在C++中,引入了一对新的操作符new/delete来动态分配和释放内存。虽然旧的malloc/free仍然有效,但强烈建议不再使用它们。因为new/delete做了一些“我们不知道”的事情。比如有一个类A,我们执行下面的操作:
A* pNew = new A(); delete pNew;
C++中总是先分配内存,然后调用A的构造函数。那么对应的操作可能是下面的样子:
A* pNew = malloc(sizeof(A)); //分配一片内存. pNew->A(); //调用构造函数. … pNew->~A(); //调用析构函数. free(pNew); //释放内存.
现在我们知道:malloc/free只是简单的执行内存分配,而new/delete在分配内存的同时,还在这片内存上执行了对象的构造或析构。
二、多维数组的动态分配
有时候我们需要动态分配一个多维数组——比如创建一幅游戏地图。那么我们可以通过动态创建来完成。多维数组的分配有多种方式,如下:
1> 直接分配:
我们用二维数组为例,这个比较容易,如下:
int (*pArr)[4] = new int[3][4]; //alloc pArr[3][4].
这样就创建了一个三行四列的二维数组,释放操作如下:
delete [] pArr; //delete it.
也可以像下面操作,比较直观:
typedef int(pARRAY)[4]; pARRAY* ppArr = new pARRAY[3];
这样也创建了一个三行四列的二维数组,释放操作和上面一样。三维、多维的操作和二维的类似。
2> 多次分配:
我们也可以通过多重分配来模拟:
int **ppArr = new int*[3]; for(int i=0; i!=3; ++i) { ppArr[i] = new int[4]; }
这样也创建了一个三行四列的二维数组,释放操作如下:
for(int i=0; i!=3; ++i) { delete [] ppArr[i]; } delete [] ppArr;
可以看出,创建、释放操作比第一种方法麻烦了不少。其余的操作基本一样。所以我们最好用第一种方式来动态创建多维数组。
三、几种new方法:
1> plain new:
这种普通的new方法我们只能通过异常检测来判断内存分配是否成功,而不是通过检测new返回的指针是否为NULL。因为C++标准规定:“plain new在分配失败后抛出std::bad_alloc异常,而不是返回NULL。”示例如下:
try { int* pInteger = new int(12); } catch(std::bad_alloc& err) { //Alloc FAILED!do something… }
像下面的检测操作是无用的:
if(pInteger == NULL) { //Alloc FAILED!do something… }
2> nothrow new:
我们可以通过nothrow来分配一片内存,这样如果分配失败,则返回NULL而不是抛出std::bad_alloc异常:
int* pInteger = new(nothrow) int(12); if(pInteger == NULL) { //Alloc FAILED!do something… }
我们可以知道,哑元nothrow是C++中全局的一个nothrow_t的const对象。
3> placement new:
如果我们频繁动态创建/释放对象,那么我们可能会用到placement new方法,这种方法通过指定一片已动态分配的内存,来在上面执行对象创建操作,而不会重新分配内存。如下:
int* pInteger = new int(12); //*pInteger = 12. pInteger = new(pInteger) int(23); //*pInteger = 23.
placement new操作只是简单的在pInterger所指向的内存上执行对象的构造。需要注意的是:placement new分配的内存需要我们自己显式调用析构函数,如:pObj->~ClassName();。
这种方法很有用,比如在一个太空游戏中要动态创建/释放很多的敌机、飞船,那么我们会用到placement new,将分配后要释放的内存简单的放到我们管理的内存池中,然后在下次有对象创建时简单的执行placement new即可。比如我们的内存池为CMemoryPool:
CMemoryPool craftPool; //飞船池.
如果我们要创建飞船,那么在需要创建时只需在内存池中查询,如果有可用的内存,则返回一片可用内存并在上面执行placement构造,否则只是创建一份即可。
CCraft* pNewCraft = 0; if(pNewCraft = craftPool.Query()) { pNewCraft = new(pNewCraft) CCraft; } else { pNewCraft = new CCraft; //内存池中没有可用内存. } //do something…
在飞船被击毁时,只需将它解除,然后添加到内存池即可:
pNewCraft->~CCraft(); //显式调用析构函数. craftPool.AddMemory(pNewCraft); //飞船被“释放”,不可用.
这样就避免了频繁的创建/释放操作使堆千疮百孔了。综上我们简单介绍了C++中动态分配内存的管理等问题。
--By:YaFengZhang
--Date:2010.12.11
--Blog:http://blog.csdn.net/ZhangYafengCPP
相关文章推荐
- C++内存分配及变长数组的动态分配
- Windows内存管理机制及C++内存分配实例(三):虚拟内存
- Windows内存管理机制及C++内存分配实例
- 全面介绍Windows内存管理机制及C++内存分配实例
- C++继承关系中的动态内存分配
- C++的动态内存分配
- 全面介绍Windows内存管理机制及C++内存分配实例
- c++ 基类、派生类都使用了动态内存分配的实例
- C++动态内存分配(堆)
- C和C++如何动态分配和释放内存,他们的区别是什么
- 全面介绍Windows内存管理机制及C++内存分配实例
- 全面介绍Windows内存管理机制及C++内存分配实例(二):内存状态查询
- 字符内存动态分配管理类(CAutoMem)
- C++的动态内存分配
- C/C++之动态内存分配比较
- C/C++内存分配管理
- Windows内存管理机制及C++内存分配实例(六):堆栈
- 【问题】c/c++函数内部动态分配的内存,函数执行完毕会释放吗?
- C++内存动态分配(转载)
- C/C++之动态分配内存