一、多维数组的注意事项
- 创建后必须逐级删除 delete[]
- 多维数组涉及多个new, 致使内存不连续,内存跳跃式访问,cache miss,遍历效率慢,会致内存碎片
#include<iostream>
int main() {
//二维数组分配内存
int** a2d = new int* [5];
for (int i = 0; i < 5; i++)
a2d[i] = new int[5];
//二维数组回收
for (int i = 0; i < 5; i++)
delete[] a2d[i];
delete[] a2d;
//三维数组分配内存
int*** a3d = new int** [5];
for (int i = 0; i < 5; i++) {
a3d[i] = new int*[5];
for (int j = 0; j < 5; j++) {
a3d[i][j] = new int[5];
}
}
//三维数组回收
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
delete[] a3d[i][j];
}
delete[] a3d[i];
}
delete[] a3d;
//用一维数组替代二维数组,运行速度要快于多维数组的遍历
int* array = new int[5 * 5];
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
array[x + y * 5] = 2;
}
}
//以上的多维数组方式会造成内存碎片问题
//因为没有一个连续的内存缓冲区,在一行中保存多维数组的所有数据
//实际上,创建了多个单独的缓冲区,每个缓冲区有一个一维数组的element,
//它们会这样分配,除非你采取某种自定义分配或者采用内存池分配。
//否则,它们会被分配到内存中完全随机的位置,可能隔得很远或则很近,
//没办法保证一定很近,这是个问题。
//每次遍历访问的时候,跳到数组的下一行(或其他维度),或者下一个子数组的时候,
//必须跳转到内存中的另一个位置来读写数据,这会导致cache miss (缓存不命中)
//这意味着我们在浪费时间从RAM中获取数据。
//如果它们恰好紧密地一起分配,那么这可能不会造成cache miss,但是不能指望一定会分配到一起,通常不会分配到一起。
//所以,用这种方式遍历多维数组要比只分配一个一维数组要慢得多,因为一维数组只分配在一行。
//最重要的一点是当你在编程和优化时,你在处理内存问题时,你可以优化的最重要的事情之一就是优化你的内存访问。
//如果你能将要访问的内存存储在一起,那么在定位数据时,会有更多的cache hits(缓存命中)以及更少的cache miss,你的程序会更快。
//如果要存储一个位图:bitmap,所以像素都在一张图片里,你可以把照片想象成照片或纹理这种二维的东西,比如像素就像一个二维数组。
//我们应该把它存储为一个2D数组?不!把它存储为一个一维数组即可。一维数组在存储图像上要好得多的多。
}