【C++】回顾C++多维指针
2016-05-19 11:15
288 查看
C++ 在堆上开辟与释放二维、三维指针详细解析
一维指针其实就相当于一维数组,不用去看书上所说的数组在内存中的首地址这些晦涩的话,以此类推 二维指针就相当于二维数组,新手对一维数组的开辟与释放比较容易熟悉;
学习C++新手通常会对指针的使用比较头疼,其实指针的概念很简单,只要能悟清楚这样一个简单的道理就能对指针有一定的认识了: 例如 int *a = new int[10]; 一维指针其实就相当于一维数组,不用去看书上所说的数组在内存中的首地址这些晦涩的话,以此类推 二维指针就相当于二维数组,新手对一维数组的开辟与释放比较容易熟悉,例如上面的a 释放就是 delete []a; a = NULL; 注意a = NULL; 必须要加上,这样是为了避免这个指针会变成“野指针”。写程序时一定要注意规范性和严谨性,避免可能会出现的错误。
二维指针动态分配内存连续问题深入分析
当我们定义一个二维指针时,如果需要存储相应的数据,就需要我们动态的分配内存,这时,有一点是需要注意的,分配内存的方法不同,内存的连续性也是不相同的;
![](http://img.blog.csdn.net/20160519111916785?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
如图所示,两种分配内存的方法都能正确的分配内存,但是内存分配的空间确实不一样的。
分析:
第一种分配方法:
首先,是对每一行分配,也就是 nWidth 中的每一个进行分配,所以,我们可以看到每一行的内存都是连续的,每一个都占据四个字节
但是,为nHeight分配内存的时候,是随机的进行分配内存,所以内存的位置是不确定的,所以,出现了第一种情况
第二种分配方法:
首先,同样是为 p 分配内存,现在 p 指向一个位置
但是,在第二句中,我们需要注意,是直接在 p[0] 出分配了所有需要的内存,所以,这个时候就全部分配完了,而且由于是一次性分配内存,故内存的地址肯定是连续的,运行结果也证明了这一点
释放内存的两种情况:
第一种情况由于是两次不同的分配内存,所以,在释放内存的时候,我们应选择不同的区域进行释放。
第二种情况,只是连续调用两次 malloc ,所以,只需要连续两次调用 free 即可完成释放。
一维指针其实就相当于一维数组,不用去看书上所说的数组在内存中的首地址这些晦涩的话,以此类推 二维指针就相当于二维数组,新手对一维数组的开辟与释放比较容易熟悉;
学习C++新手通常会对指针的使用比较头疼,其实指针的概念很简单,只要能悟清楚这样一个简单的道理就能对指针有一定的认识了: 例如 int *a = new int[10]; 一维指针其实就相当于一维数组,不用去看书上所说的数组在内存中的首地址这些晦涩的话,以此类推 二维指针就相当于二维数组,新手对一维数组的开辟与释放比较容易熟悉,例如上面的a 释放就是 delete []a; a = NULL; 注意a = NULL; 必须要加上,这样是为了避免这个指针会变成“野指针”。写程序时一定要注意规范性和严谨性,避免可能会出现的错误。
//二维指针的开辟与释放 int **b = NULL; b = new int*[10]; for(int i = 0; i != 10; ++i) { b[i] = new int[50]; memset(b[i], 0, sizeof(int)*50); } //这样就在堆上开辟了int类型的二维指针,大小为10*50,相当于在堆上一个二栈数组int b[10][50]; for(int i = 0; i != 10; ++i) { delete []b[i]; b[i] = NULL; } delete []b; b = NULL; //三维指针的开辟与释放 int ***a = NULL; a = new int**[10]; for(int i = 0; i != 10; ++i) { a[i] = new int*[50]; for(int j = 0; j != 50; ++j) { a[i][j] = new int[30]; memset(a[i][j], 0, sizeof(int)*30); } } //这样就在堆上开辟了int类型的三维指针,大小为10*50*30,相当于在栈上一个二维数组int a[10][50][30]; for(int i = 0; i != 10; ++i) { for(int j = 0; j != 50; ++j) { delete []a[i][j]; a[i][j] = NULL; } delete []a[i]; a[i] = NULL; } delete []a; a = NULL;
二维指针动态分配内存连续问题深入分析
当我们定义一个二维指针时,如果需要存储相应的数据,就需要我们动态的分配内存,这时,有一点是需要注意的,分配内存的方法不同,内存的连续性也是不相同的;
#include <cstdlib> #include <iostream> using namespace std; #define nWidth 3 #define nHeight 4 //内存是否连续分配问题 int main(int argc, char *argv[]) { int **p = NULL; p = (int**)malloc(nWidth*sizeof(int*)); if(p == NULL) return -1; cout<<"内存的不连续分配:"<<endl; for(int j = 0; j< nWidth; j++) { p[j] = (int*)malloc(nHeight*sizeof(int)); if(p[j] == NULL) return -1; } for(int i = 0; i < nWidth; i++) for(int j = 0; j < nHeight; j++) { printf("%p ",&p[i][j]); if(j == nHeight-1) cout<<endl; } cout<<endl; for(int j = 0; j < nWidth; j++) { free(p[j]); p[j] = NULL; } free(p); p = NULL; int **q = NULL; q = (int**)malloc(nWidth*sizeof(int*)); if(q == NULL) return -1; cout<<"内存的连续分配:"<<endl; q[0] = (int*)malloc(nWidth*nHeight*sizeof(int)); if(q[0] == NULL) { free(q); return -1; } for(int i = 1;i < nWidth; i++) q[i] = q[i-1] + nHeight; for(int i = 0; i < nWidth; i++) for(int j = 0; j < nHeight; j++) { printf("%p ",&q[i][j]); if(j == nHeight-1) cout<<endl; } cout<<endl; free(q[0]); q[0] = NULL; free(q); q = NULL; system("PAUSE"); return EXIT_SUCCESS; }
如图所示,两种分配内存的方法都能正确的分配内存,但是内存分配的空间确实不一样的。
分析:
第一种分配方法:
首先,是对每一行分配,也就是 nWidth 中的每一个进行分配,所以,我们可以看到每一行的内存都是连续的,每一个都占据四个字节
但是,为nHeight分配内存的时候,是随机的进行分配内存,所以内存的位置是不确定的,所以,出现了第一种情况
第二种分配方法:
首先,同样是为 p 分配内存,现在 p 指向一个位置
但是,在第二句中,我们需要注意,是直接在 p[0] 出分配了所有需要的内存,所以,这个时候就全部分配完了,而且由于是一次性分配内存,故内存的地址肯定是连续的,运行结果也证明了这一点
释放内存的两种情况:
第一种情况由于是两次不同的分配内存,所以,在释放内存的时候,我们应选择不同的区域进行释放。
第二种情况,只是连续调用两次 malloc ,所以,只需要连续两次调用 free 即可完成释放。