1.首先,一维数组是指针
int array[10];
int* array=new int[10];
两种表达一样吗?(第一种有分配内存吗?应该没有吧,毕竟没有new)
这仅仅是分配10个int大小(sizeof(int))的内存,没有任何值在里面,array也仅仅是一个指针,指向这段内存。
二维数组:
int a2d[10][10];//声明
int** array2d=new int*[10];
有趣的是第二行,也仍然仅仅是分配内存。
这里声明了array2d,它是指针,指向一个一维数组,而这个一维数组存储的不是int类型,而是int*类型,也就一维数组中分配了10个指针大小的内存。而且这个array2d也是指针,指向这个一维数组。
继续第二行:
int** array2d=new int*[10];
for (int i=0;i<10;i++)
{
array2d[i]=new int[10];
}
array2d[i]是一个指针,并且每个指针i都指向一个一维int数组,大小是10个sizeof(int)
因此是个二维数组,二维数组也就是一个pointer which point to one dimension array of pointers,而这个数组每个元素又指向一个数组。
可以想象为表格索引。
继续深入三维,可以想象成为立方体存储块。
类似二维数组,首先说明三维数组是一个指针,这个指针指向pointers which point to pointers which point to pointers. 这pointers里面的复数大小,取决于申请的空间大小。
int*** array3d=new int**[10];
for (int i=0;i<10;i++)
{
array3d[i]=new int*[10];
for (int j=0;j<10;j++)
{
array3d[i][j]=new int[10];
}
}
其中,array3d,array3d[i],array3d[i][j]都是指针。array3d[][]是指向int数组的指针。而另外两个则都是指向pointer数组的指针。(这么说不一定严格准确,仅仅为了理解)这里面说的数组严格意义上对应的是内存空间。
int*** array3d=new int**[10];
for (int i=0;i<10;i++)
{
array3d[i]=new int*[10];
for (int j=0;j<10;j++)
{
int** ptr=array3d[i]//能理解这一个变化吗?为什么是int**
ptr[j]=new int[10];
}
}
回答注释中的问题,因为恰恰是array3d[i]是一个pointer which point to int*[10],而这10个单位内存空间也分别存储着一个pointer which point to int[].也就是array3d[i][j]=new int[10];
从底层往上面解释:每一个pointer 也就是 array3d[][]指向int[10],而一共有10个这样的指针(由array3d[i]指向这10个指针),因此可以指向1010个int内存空间。而10个这样的array3d[i]作为一个数组(内存块),由array3d指向,因此array3d也就指向1010*10个int内存。
所以说,可以想象成立方体,然后坐标系x,y,z范围都是1-10。
你不妨可以对应一下x,y,z都分别是array3d[][],array3d[],array3d这三个哪一个?然后其每一个刻度都是int还是pointer.
参考答案:
如果x是array3d[][],y是array3d[],z是array3d。那么x对应的刻度1-10是对应int,其他对于指针pointer.
2.回到二维,观察delete:
delete[][] array2d;//会报错
delete[] array2d;//语法正确,但会导致内存泄漏
第二个我们只是删除了10个指针也就是删除了10sizeof(int)的内存空间,但是并没有删除这10个指针所指向的1010个sizeof(int)内存空间,因此我们将找不到这个1010个sizeof(int)的内存空间了,因为这10个指针没了。–>内存泄漏(memory leak)
因此需要:
for (int i=0;i<10;i++)
{
array2d[i]=new int[10];
}
for (int i=0;i<10;i++)
{
delete[] array2d[i];
}
delete[] array2d;//还需要此步骤才能彻底删除
array2d并不拥有连续的一整个个100sizeof(int)的内存空间,而是拥有10 separate buffer of 10 sizeof(int)空间,是 10个单独的10sizefo(int)空间,而不是直接100个。
但是我们可以随意存储这1010sizefo(int)中。
但是这种存储方式会比较慢,因为需要iterate,我们需要先寻找10个pointers which point to 一维数组,然后再降维进入一维数组。
远不如直接存储在100*sizeof(int)个一维数组上面快。因为一维数组是一段连续的空间。
因此,我们可以这样写代码:
int** array2d=new int*[10];
for (int i=0;i<10;i++)
{
array2d[i]=new int[10];
}
int* array2d=new int[10*10];
for (int i=0;i<10;i++)
{
for (int j=0;j<10;j++)
{
array2d[i]=new int[j+i*10]; //将步长改为10
}
}
cool!
我们可以借此存储所有的二维、三维数组,比如图片的pixel,立方体的voxel。
欢迎大佬指正