用C ++实现2d数组,内存更少

时间:2015-04-17 20:31:47

标签: c++ arrays algorithm

我需要一个2d数组,它是该类的一个字段。 x是宽度,y是高度。

我写了这样的代码:

#include <iostream>

int main(){
    char ** tab;
    int x, y;
    std::cin >> x >> y;
    tab = new char* [x+2];
    for (int i = 0; i < x+2; i++) {
        tab[i] = new char [y+2];
    }
}

它有效。问题是需要太多内存(示例数据需要16kb而我只能使用5kb)是否有一种简单(或不安)的方式来实现它?

我能想到的唯一解决方案就是tab[(x+2)*(y+2)],但是我必须改变整个程序并用简单的算法来计算数组中的位置,但它需要重写大量的代码所以我想避免这种情况。

编辑:5kb是必需的,因为它是学校的项目:)程序在96次测试中完成运行(满分100次),但是在这一次它因内存而停止。 edit2:如何在一个char中存储多个valueas?它会非常复杂吗?

5 个答案:

答案 0 :(得分:2)

我认为最好的方法是将它封装到2d数组类。它适用于一维数组,但您可以通过getter和setter以及您选择的索引来访问它。这是我能想到的最简单,最优雅的解决方案。

答案 1 :(得分:2)

编辑:我厌倦了看到太多不正确的答案获得投票,所以我做了一些实际的实验来证明我的主张的有效性并重写了我的答案。

tl; dr tab是一个指向char的指针数组。这意味着tab不存储char(每个占用8位),而是存储x指针,每个指针通常采用64位。您需要找到一种方法来使用tab作为指向单个char数组的指针:char * tab


问题

在这个循环中:

for (int i = 0; i < x+2; i++) {
  tab[i] = new char [y+2];
}

你正在运行new x + 2次(顺便说一下,为什么+2 ??)。如您所知,new返回指针而不是 chars 。它为您要求的数据类型分配内存,即。 char 然后返回指向该内存地址的指针。因此,在循环中对new的调用分配8位。由于new返回一个内存地址,你需要将它存储在某个地方。谢天谢地,你已经用这一行分配了存储该地址的空间:

tab = new char* [x+2];

现在你不是要求newchar数组保留空间,而是要求它为指向char的指针数组预留空间。

在大多数现代架构中,指针需要64位。这些指针存储在tab指向的内存地址中的堆上。 ie tab[0]保存第一个指向char的指针,tab[1]保存第二个指针等等......这些指针保存已分配用于保存字符的额外内存的位置。

所以总的来说,你是用这一行为x+2指针分配空间:

tab = new char* [x+2];

(x+2)*(y+2)字符与此行:

tab[i] = new char [y+2];

如果你进行数学计算,那么对于字符加上 (x+2)*8B的{​​{1}}来说就是chars。通过查看方程式,您将看到对于给定数量的字符,即对于任何x * y ,如果(x+2)*(y+2)*1B大于{{1},您将看到更多的内存使用量}。

为了测试这个,我在你的代码上运行了valgrind massif工具(除了我摆脱了x,结果如下:

y

了解每次+2增加时内存使用量如何增加8B。这是用于存储指针数组的空间分配。请注意,对于| x | y |useful-heap(B)| |----|---|--------------| | 0 | 1 | 0 | | 1 | 0 | 8 | | 1 | 1 | 9 | | 1 | 2 | 10 | | 1 | 3 | 11 | | 2 | 0 | 16 | | 2 | 1 | 18 | | 2 | 2 | 20 | | 3 | 0 | 24 | | 3 | 1 | 27 | | 20 | 0 | 160 | |100 | 0 | 800 | 个案例,根本没有存储字符...因此当xy=0使用800B内存时绝对没有任何内容。

fyi,massif还报告了由于最小分配规模,效率等而系统为您做出的额外分配,但我上面给出的数字是地块声称您要求的确切数量


如何解决?

关键是要重新安排你如何存储字符以及如何解决它们。你正在存储字符,所以你可以制作一个大的字符数组,并找到一种不同的索引方式。除了字符本身之外,这不需要堆分配。

我还建议远离原始数组和指针,并使用std :: array或std :: vector,但我认为你已被特别告知使用它们进行分配......

答案 2 :(得分:1)

如果您使用&#39; -Os&#39;编译代码标志它将优化内存。

这不是非常C ++ - 但是您可以使用宏来访问和像矩阵一样的数组:

#define TAB(col,row) tab[col*column_length+row]

正确的方法将创建一个用于封装所有这些的类。

答案 3 :(得分:0)

您还没有指定输入的2D数组大小(测试中的x和y是多少)。

请注意&#34; new&#34;具有最小分配大小。

如果调用一堆新的char [1]数组(比如x = 1,y = 10000), 然后你分配min malloc size * 10000;不是1 * 10000。 我相信最小大小是32或64字节。

如果您可以一次性分配所有内存(作为单个阵列分配),您将最小化所需的内存量。 例如新char [x * y]

答案 4 :(得分:-1)

我相信你回答了自己的问题,我认为没有办法让它占用更少的空间,因为char的可变大小会决定它。