Эффективно собирать данные из нескольких одномерных массивов в один одномерный массив - PullRequest
2 голосов
/ 08 января 2012

У меня есть заранее написанная функция в C, которая заполняет одномерный массив данными, например,

int myFunction(myData **arr,...);


myData *array;
int arraySize;
arraySize = myFunction(&arr, ...);

Я хотел бы вызывать функцию n раз подряд с немного отличающимися параметрами (n зависит от ввода пользователя), и мне нужны все данные, собранные в один массив C впоследствии. Размер возвращаемого массива не всегда фиксирован. Ох, и myFunction делает распределение памяти внутри. Я хочу сделать это эффективным способом памяти, но использование realloc в каждой итерации не является хорошей идеей.

У меня есть все доступные функции C++ (проект находится в C++, просто используется библиотека C), но использование std::vector не годится, потому что собранные данные позже отправляются в функцию с определением, аналогичным:

void otherFunction(myData *data, int numData, ...);

Есть идеи? Единственное, о чем я могу думать, это realloc или использование std::vector и копирование данных в массив впоследствии, и это не звучит слишком многообещающе.

Ответы [ 4 ]

3 голосов
/ 08 января 2012

Использование realloc() в каждой итерации для меня звучит как очень хорошая идея по двум причинам:

  1. "не звучит как хорошая идея" - это то, что люди обычно говорят, когда они не установили требования к производительности для своего программного обеспечения, и они не проверили свое программное обеспечение на соответствие требованиям к производительности, чтобы увидеть, есть ли необходимость улучшить его.

  2. Вместо того, чтобы каждый раз перераспределять новый блок, метод realloc просто продолжит расширять ваш блок памяти, который, вероятно, будет находиться наверху кучи памяти, поэтому он не будет тратить время на обход списки блоков памяти или копирование данных. Это верно при условии, что любая память, выделенная myFunction(), освобождается до ее возврата. Вы можете проверить это, посмотрев на указатель, возвращенный realloc() и убедившись, что он всегда (или почти всегда (* 1)) точно такой же указатель, как тот, который вы дали для перераспределения.

EDIT (* 1) некоторые среды выполнения C ++ реализуют две кучи, одну для небольших выделений и одну для больших выделений, поэтому, если ваш блок выделяется в куче для небольших блоков, а затем он становится большим, есть вероятность, что он будет перемещен один раз в кучу для больших блоков. Поэтому не ожидайте, что указатель всегда будет одним и тем же; просто большую часть времени.

1 голос
/ 08 января 2012

Просто скопируйте все данные в std::vector. Вы можете позвонить otherFunction на вектор v с

otherFunction(&v[0], v.size(), ...)

или

otherFunction(v.data(), v.size(), ...)

Что касается ваших требований к эффективности: мне кажется, что вы оптимизируете преждевременно. Сначала попробуйте этот вариант, затем измерьте его скорость и ищите другие решения, только если он действительно слишком медленный.

1 голос
/ 08 января 2012

Если вы знаете, что собираетесь вызывать функцию N раз, а возвращаемые массивы всегда имеют длину M, то почему бы вам просто не выделить один массив M * N изначально?Или, если вы не знаете ни M, ни N, установите максимальный наихудший случай.Или M и N оба зависят от пользовательского ввода?

Затем измените способ вызова функции получения пользовательского ввода так, чтобы указатель массива, который вы передаете, фактически смещался в этот большой массив, поэтомучто он хранит данные в нужном месте.Затем, следующая итерация, смещение дальше и повторный вызов.

0 голосов
/ 08 января 2012

Я думаю, что лучшим решением было бы написать собственный класс 1D-массива с некоторыми необходимыми вам методами.

В зависимости от того, как вы пишете класс, вы получите такой результат.(извините, плохая грамматика) ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...