最近刚刚把用循环分配二维数组、三维数组的堆内存空间搞清楚,但是又见到了这种分配方法,但是不知道怎么释放空间啊:
int (*p)[2000]=new int[1000][2000];//给二维数组p[1000][2000]分配空间;
请问怎样释放这种方法分配的空间啊?
还有,这种分配方法能推广到三维或更多维的情况吗?请各位大侠不吝赐教啊!!!
分配
T **m_pptMat
m_pptMat = new T*[m_iRow];
for (int i = 0; i < m_iRow; ++i)
m_pptMat[i] = new T[m_iCol];
删除
for (int i = 0; i < m_iRow; ++i)
delete m_pptMat[i];
delete m_pptMat;
赋值
for (int i = 0; i < m_iRow; ++i)
{
m_pptMat[i] = new T[m_iCol];
memcpy(m_pptMat[i], cmSrc.m_pptMat[i], sizeof(T) * m_iCol);
}
不用循环我试过,不行,不知道别人有没有高招。
应该是这样的。
int (*p)[5];
p=new int[5][5];
.....
delete []p;
你可以看一下这个程序
#include <iostream.h>
int main(){
int (*a)[1000];
a=new int[1000][1000];
delete []a;
return 0;
}
在2k下用任务管理器看他的内存分配和释放,你会发现他先分配了4M空间,然后释放了4M
// int (*p)[2000]=new int[1000][2000];//
int* buf = new int[1000*2000] ;
int (*p)[2000] = (int(*)[2000])buf;
p[100][100] = 1 ;
p[500][500] = 100 ;
p[999][1999] = 100 ;
cout<<buf[1000*2000-1]<<endl ;//test buf is good
delete buf ;
没什么好说的,几次 new,对应应该有几次 delete。
p = net int[11][11][11][11][11][11][11];
delete[] p;
//分开看:
int (*p)[2000]=new int[1000][2000];//给二维数组p[1000][2000]分配空间;
//定义一个数组指针,指向int [2000]
int (*p)[2000] = NULL;
//申请一个二维数组,一维的长度和p的类型长度一样都是 2000
p = new int[1000][2000];
//可以这样便利这个数组
for( int i = 0; i < 100; i++)
{
for(int j = 0; j < 200; j++)
{
p[j] = 0;
}
p++;
}
设:
int (*p)[n-1][n-2][n-3]....[1] = new int[n][n-1][n-2]...[1];
方法1. delete []p;
方法2. delete p; //这种方法的执行效果来看与方法1一样,但写法不标准,可能会有warning.
如果:
int *p = new int [n];
就必须用:
delete []p;
解释:
多维数组在底层都是连续的一块一维数组,在new 时,数组大小值被编译器值于某个地方,delete[]时找到这个值,然后释放掉.为什么delete p也可以呢,因为编译器通过p定义时的形式:int (*p)[n-1][n-2][n-3]....[1] = new int[n][n-1][n-2]...[1];可得知p是一个指向数组的指针,而不是指向一个元素的指针,所以就可以按delete[]处理.
而对于一维数组,则不能通过delete p来释放全部数组空间,因为delete p是释放p指向的一个元素空间.
下面是测试程序:
#include <iostream>
#include <stdlib.h>
using namespace std;
class Test {
public:
static int count;
Test() { count++; }
~Test() { --count; }
};
int Test::count = 0;
int main() {
Test (*pTest)[5][10] = new Test[3][5][10];
// Test *pTest = new Test[10]; // 一维数组.
cout << "Test::count =" << Test::count << endl;
delete []pTest;
// delete pTest;
cout << "Test::count =" << Test::count << endl;
system("pause");
return 0;
}
通过观察Test::count即可发现数组空间是否完全释放.而不用调用任务管理器来观察内存是否泄露.
首先,我在先前的贴子说"而对于一维数组,则不能通过delete p来释放全部数组空间,因为delete p是释放p指向的一个元素空间."
是错误的.
不论是几维数组,对于基本类型(如int,long等)数组或非基本类型但不会在析构函数中释放内存空间的数组:
以下两种方式:
delete p;
delete []p
都不会造成内存泄露!
delete 与 delete[]语句分两步执行:
1.调用 operator delete(p);或operator delete[](p);
这步在底层将调用free(p);
2.调用数组元素对应的析构函数:
对于p指向一维数组的情况:
如果是delete p;将只调用数组的第一个元素的析构函数,如果是delete []p将调用全部元素的析构函数.如果元素是基本类型,则第二步什么也不做.
至于在C中用free(a)一个数组,总不会造成内存泄露的.
三维的情况呢,能这样写吗:
int (*p)[20][30]=(int(*)[20][30])malloc(10*20*30*sizeof(int));
——我认为能,都强制转换了,还有什么不能的?
就是free(p);
指针传入free后,统统被作为void型的指针接收进去了,所以不管原来曾经多么复杂过,只要还是那个首地址,free只管释放,别的什么都不管。
我觉得 c 语言里是没有真正的多维数组,本质上都是一维的。
一维和多维在内存中的存放方式没有任何区别,都是逻辑上连续的一段内存。
我们在分配内存时也没有对是一维还是多维做任何区分,这也就是为什么 malloc 的参数列表里只需要一个空间大小参数,返回的都是 void * 类型的指针。
那么我们是如何实现逻辑上的多维呢?
我想这里是我们巧妙的运用了指针运算,我们通过定义一个指向多维数组的指针如:int (*p)[20][30],通过指针特殊的寻址算法,找到我们需要的每一个元素。这样的话就在我们的大脑里虚构成一个多维的数组的假像,而且这种虚拟是合理的,能让我们方便的驾驭数组。
至于 free 是如何做到正确地释放内存?
我个人的理解是在用 malloc 分配内存时,应该是有个记录,记录了分配内存的大小等信息。具体这个记录存放在什么位置,它是如何管理的,我不知道。
在 free 眼里,它所接触到的都是一维数组,或者讲是一段内存,它是按照记录表里的信息来决定该释放多大的内存。
下面是一篇参考文章,稍有点过时,但能提供一些比较高级的技术细节:
http://gee.cs.oswego.edu/dl/html/malloc.html
这里你能找到 malloc 的源代码:
ftp://gee.cs.oswego.edu/pub/misc/