Как показывает практика, освобождение, скажем так, большого (от полумиллиона строк) двумерного массива затягивается во времени. Причем, если реаллокация производилась во время длительной работы над чем-то, то она, в общем, происходила незаметно. Освобождение же этого «монстра» реально вешает приложение на выходе из него на десятки секунд. Что вызовет однозначную реакцию со стороны пользователя — он прибьет его не дожидаясь.
Так вот, выход есть, и он прост до безобразия. При чем, он заодно несет в себе плюшки и в ускорении аллокации.
Всего-то надо — отказаться от двумерного (скольугодно мерного) массива в пользу одномерного.
Давайте сравним двумерный и одномерный подходы.
Это остается за скобками:
#define ARRAY_WIDTH 10
#define ARRAY_HEIGHT 10
Было:
int **my_array;
что требовало создать сначала массив указателей:
my_array = (int**) malloc(sizeof(int*) * ARRAY_HEIGHT);
затем пробежаться по нему и присвоить каждому этому указателю значение адреса памяти в котором лежит массив значений. Разумеется, надо эту память для начала выделить. Вот такая борода:
for (i = 0; i != ARRAY_HEIGHT; ++i)
if (!(my_array[i] = (int*) malloc(sizeof(int) * ARRAY_WIDTH)))
{
printf(«Error allocating my_array[%d][%d]\n», ARRAY_HEIGHT, i);
return -1;
}
Удаление этого дела выглядит так же «красиво», даже если забыть про то, что оно может дико тормозить.
Что же у нас получается если мы делаем одномерный массив?
int *my_array;
Легко и элегантно мы за один шаг создаем все:
my_array = (int*) malloc(sizeof(int) * ARRAY_WIDTH * ARRAY_HEIGHT);
Удаляем так же просто и быстро:
free(my_array);
Единственный вопрос, а как же нам поиметь двумерные данные из нашего быстрого, но одномерного хранилища? my_array[i][j] тут увы бессильно. Любой бородатый сишник поднимет меня на смех с этим вопросом, для тех же, кто еще не догадался правильный ответ:
my_array[i * ARRAY_HEIGHT + j]
Любая дополнительная размерность добавляется в этот метод аналогично.
Так вот, выход есть, и он прост до безобразия. При чем, он заодно несет в себе плюшки и в ускорении аллокации.
Всего-то надо — отказаться от двумерного (скольугодно мерного) массива в пользу одномерного.
Давайте сравним двумерный и одномерный подходы.
Это остается за скобками:
#define ARRAY_WIDTH 10
#define ARRAY_HEIGHT 10
Было:
int **my_array;
что требовало создать сначала массив указателей:
my_array = (int**) malloc(sizeof(int*) * ARRAY_HEIGHT);
затем пробежаться по нему и присвоить каждому этому указателю значение адреса памяти в котором лежит массив значений. Разумеется, надо эту память для начала выделить. Вот такая борода:
for (i = 0; i != ARRAY_HEIGHT; ++i)
if (!(my_array[i] = (int*) malloc(sizeof(int) * ARRAY_WIDTH)))
{
printf(«Error allocating my_array[%d][%d]\n», ARRAY_HEIGHT, i);
return -1;
}
Удаление этого дела выглядит так же «красиво», даже если забыть про то, что оно может дико тормозить.
Что же у нас получается если мы делаем одномерный массив?
int *my_array;
Легко и элегантно мы за один шаг создаем все:
my_array = (int*) malloc(sizeof(int) * ARRAY_WIDTH * ARRAY_HEIGHT);
Удаляем так же просто и быстро:
free(my_array);
Единственный вопрос, а как же нам поиметь двумерные данные из нашего быстрого, но одномерного хранилища? my_array[i][j] тут увы бессильно. Любой бородатый сишник поднимет меня на смех с этим вопросом, для тех же, кто еще не догадался правильный ответ:
my_array[i * ARRAY_HEIGHT + j]
Любая дополнительная размерность добавляется в этот метод аналогично.