Cpp_Basic---13/N(new/delete and 多维数组)

2017-01-11 15:23:19来源:oschina作者:OSer_Merlin人点击

第七城市

修订历史:

初稿 (多维数组的分配&释放, 推荐做法, 练习三维数组)----2017/1/10
多维数组问题:C Vs C++, 怎么进行多维数组的分配?(包括初始化)
C Vs C++, 怎么进行多维数组的正确释放?
各种分配方式的优缺点, 以及推荐方式.
练习一下3维数组的推荐分配方式, 要不你也试试?
malloc/free

在malloc/free的时候, 多维数组, 指针数组, 用法如下: (注意强转; 注意分配是否成功; 注意释放之前的NULL判断; 注意分配匹配释放)


#include
#include
void case_test_1();//multi-array
void case_test_2();//multi pointer array
int main(void){

case_test_1();
//case_test_2();
return 0;
}
void case_test_1(){

//1. array[2]
int *array = (int*)calloc(2, sizeof(int));
//if(array==NULL)........
array[0] = 0;
array[1] = 1;
printf("%d/t%d/n", array[0], array[1]);
free(array);

//2. array[2][3]
int (*array_1)[3] = (int(*)[])calloc(2*3, sizeof(int));
//if(array_1==NULL)........
//init the elem of array_1

free(array_1);

}
void case_test_2(){
//p[0]
int *p = (int*)calloc(1,sizeof(int));
//*p = 0;
p[0] = 0;
printf("%d/n", *p);
free(p);

/****************watch out!************************************/
//int *array[3];int*
int **array = (int**)calloc(3, sizeof(int*));
//if(array==NULL) ....

int i;
for(i=0; i<3; i++){
*(array+i) = (int*)calloc(1, sizeof(int));
//if(*(array+i) == NULL) ....
*array[i] = i;//
}

printf("%d/t", *array[0]);
printf("%d/t", *array[1]);
printf("%d", *array[2]);

//watch out free process
for(i=0; i<3; i++){
free(array[i]); //the type of every elem in array is int*
}

free(array);
} new/delete

如果只是一维, 那么new/delete, new[]/delete[]都是很简单的, 如下:


#include
#include
using namespace std;
void test_case_1();
int main(void)
{
test_case_1();
return 0;
}
void test_case_1(){
int *array = new int[3];
for(int i = 0; i < 3; i++){
array[i] = 0;
}
delete[] array;
array = NULL;
}

(注意上面的初始化, 不要用memset, 不一定能成功; 自己遍历一下初始化方便)


下面的指针数组, 可以达到动态数组的目的:


void test_cast_2(){
//array*[3], pointer array
int **array = new int *[3];
for(int i=0; i<3; i++){
//array[i]=new int [5]; //array size 5;
array[i] = new int; //array size 1;
*array[i] = i;
}
//0, 1, 2
for(int i=0; i<3; i++){
cout << *array[i] << endl;
}
for(int i=0; i<3; i++){
delete array[i]; //delete[] array[i], if u write: array[i]=new int [5];
array[i] = NULL;
}
delete[] array;
array = NULL;
}

当然, 还有一种方式, 声明指向二维&多维数组的指针, 然后动态创建:


语法大概是:


类型名 (*指针名)[下标表达式1][下标表达式2]...;


案例:


int (*p)[3];
p = new int[2][3];
//init
for (int i=0; i<2; i++)
{
for (int j=0; j<3; j++)
{
//*(*(p+i)+j) = 0;
p[i][j] = 0;
}
}

但是这里的第二维的长度3, 必须显示指定或者常量表达式, 例如:


int size = 4;
int (*p)[size] = new int[3][4];

上面的代码就会报错 "表达式的计算结果不是常量"


必须改成:


const int size = 4;
int (*p)[size] = new int[3][4];
return 0;

上面这段代码, 如果写成C的风格, 可以写成如下形式:


//array[3][4]
int (*p)[4] = calloc(3*4, sizeof(int));
//if(!p) ....
//init array[3][4];

free(p); 小结:

对上面总结一下, 其实C++并没有提供真正的多维数组分配机制, 不过可以学习C中对于多维数组的处理(指针数组, 以及普通元素的多维数组)但是各种分配方式之间, 也有一定的差别, 小结如下:


方式1:
Type (*ptr)[n] = new Type[m][n];
delete[] ptr;

其中n必须是常量或者常量表达式, 并且这样做调用比较直观, 缺点是, 缺乏动态属性. (并且这样分配的是连续内存, 可能存在分配失败的情况)----对象的析构器可以正常调用.

方式2:(推荐)
Type ** ptr = new Type[m]; //第一维个数为m
for( int i=0; i < m; i++){
ptr[i] = new Type[n]; //第二维的个数为n
}
delete[] ga[i];
delete[] ga; 不推荐

不推荐这样:


A** ga = new A*[m];
ga[0] = new A[m*n];

为什么? 因为虽然作为二维数组相应的空间被分配了, 并且连续, 但是理解起来不是那么清晰, 也就是说, 来维护他的人, 必须理解&接受这种非"常规"的方式. (简单, 易于维护才是上策呀;)


也不推荐下面这样:


A* ga = new A[m*n];
delete []ga;

原因和上面一样, 不易于理解.


当然, 如果你能够用上底层数据结构, 或者STL容器, 那么请用容器吧.


一般如果没有连续分配之类的限制, 我推荐:


int **array2D;
//假定数组第一维长度为m, 第二维长度为n
//动态分配空间
array2D = new int*[m];
for( int i=0; i{
array2D[i] = new int[n];
}
//释放
for( int i=0; i{
delete[] array2D[i];
array2D[i] = NULL;
}
delete[] array2D;
array2D = NULL;

最后练习一下, 三维数组的分配试试:


void test_cast_3(){
//array[3][2][1];
int ***array3D;
array3D = new int**[3];
for(int i=0; i<3; i++){
array3D[i] = new int*[2]; //create for int* a[0], int* a[1]
for(int j=0; j<2; j++){
array3D[i][j] = new int; //or new int[1]; but when u delete it, u using delete[]
*array3D[i][j] = 22;
cout << "array3D[" << i << "][" << j << "]" << "=" << *array3D[i][j] << "";
}
cout << endl << "-----------------------------------------" << endl;
}
//now delete it: from inner to outter
for(int i=0; i<3; i++){
for(int j=0; j<2; j++){
delete array3D[i][j]; // watch out "array3D[i][j] = new int; "
array3D[i][j] = NULL;
}
delete[] array3D[i];
array3D[i] = NULL;
}
delete[] array3D;
array3D = NULL;
}

释放的时候, 如果你写成下面这个样子, 那我就啥也不说了:


for( int i=0; i<3; i++ )
{
for( int j=0; j<2; j++ )
{
delete array3D[i][j];
}
delete array3D[i];
}
delete array3D;

先这样, 以后有问题, 再说.


merlin


2017/1/10

第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台