为什么当行>列时数组的内存占用量更大

why is the memory footprint of array larger when row > column

本文关键字:内存 数组 gt 为什么      更新时间:2023-10-16
int **arr_a;//4x268435456
arr_a = new int*[4];
for (int i = 0; i < 4; i++) {
    arr_a[i] = new int[268435456];
    for (int j = 0; j < 268435456; j++) {
        arr_a[i][j] = j;
    }
}
int **arr_b;//268435456x4
arr_b = new int*[268435456];
for (int i = 0; i < 268435456; i++) {
    arr_b[i] = new int[4];
    for (int j = 0; j < 4; j++) {
        arr_b[i][j] = j;
    }
}

理论上:

arr_a:
    sizeof(int**) + 4 * sizeof(int**) + 4 * 268435456 * sizeof(int)
    =4G
arr_b :
    sizeof(int**) + 268435456 * sizeof(int*) + 268435456 * 4 * sizeof(int)
    =6G

但实际上:

arr_a = 4G

arr_b = 10.6g ???为什么....

环境:Win10 64bit 32g RAM VS2017

我的结果

您看到小对象的分配开销结果。除了阵列本身中的四个整数外,new int[4]还在这两个方面造成开销:

  • 最小分配大小 - 分配器返回的数据块具有最小尺寸,通常至少32个字节,您仅使用16个字节
  • 簿记 - 除了为您提供内存外,分配器存储了一小部分数据,以帮助您在调用delete[]时做正确的事情。

这两个开销将您需要的内存量乘以:

  • 64位系统上的268435456 * sizeof(int*)是2G
  • 假设32字节分配,268435456 * 32是另一个8G

当您处理大型对象(例如arr_a的元素(时,与分配大小相比,开销非常小,您可以安全地忽略它:只有五个分配,我们正在谈论几百个字节4G总分配。当对象很小时,额外的分配与"有效载荷"的大小相当,甚至可能在某些极端情况下超过它。

每个堆分配都带有开销,因此Heap Manager可以跟踪您要求的块。您还需要将其分解为算术。这不像您要求的块的大小那样简单。

这里有一个很好的概述(尽管Windows 8(。