Как правильно объявлять и инициализировать (большой) массив двумерных объектов в c ++? - PullRequest
0 голосов
/ 29 июля 2011

Мне нужно создать большой двумерный массив объектов.Я читал некоторые связанные вопросы на этом сайте и другие, касающиеся multi_array, matrix, vector и т. Д., Но не смог собрать их вместе.Если вы рекомендуете использовать один из них, пожалуйста, переведите следующий код.

Некоторые соображения:

  • Массив несколько большой (1300 x 1372).
  • Возможно, я работаю с более чем одним из них одновременно.
  • В какой-то момент мне придется передать его функции.
  • Скорость - это большой фактор.

Два подхода, о которых я думал, были:

Pixel pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
    for(int j=0; j<1372; j++) {
        pixelArray[i][j].setOn(true);
        ...
    }
}

и

Pixel* pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
    for(int j=0; j<1372; j++) {
        pixelArray[i][j] = new Pixel();
        pixelArray[i][j]->setOn(true);
        ...
    }
}

Какой здесь правильный подход / синтаксис?

Редактировать:

В нескольких ответах предполагалось, что Pixel является небольшим - я упустил подробности о Pixel для удобства, но он не маленький / тривиальный.Он имеет ~ 20 членов-данных и ~ 16 функций-членов.

Ответы [ 6 ]

4 голосов
/ 29 июля 2011

Ваш первый подход распределяет все по стеку, что в противном случае нормально, но приводит к переполнению стека, когда вы пытаетесь выделить слишком много стека.В современных ОС ограничение обычно составляет около 8 мегабайт, поэтому размещение массивов из 1300 * 1372 элементов в стеке не вариант.

Ваш второй подход выделяет 1300 * 1372 элементов в куче, что является огромной нагрузкой дляраспределитель, который содержит несколько связанных списков с частями выделенной и свободной памяти.Также это плохая идея, тем более что пиксель кажется довольно маленьким.

Я бы сделал следующее:

Pixel* pixelArray = new Pixel[1300 * 1372];
for(int i=0; i<1300; i++) {
    for(int j=0; j<1372; j++) {
        pixelArray[i * 1372 + j].setOn(true);
        ...
    }
}

Таким образом, вы выделяете один большой кусок памяти в куче.Стек счастлив, как и распределитель кучи.

0 голосов
/ 29 июля 2011

Я бы хотел использовать std :: vector

typedef  std::vector<Pixel>       PixelRow;
typedef  std::vector<PixelRow>    PixelMatrix;

PixelMatrix   pixelArray(1300, PixelRow(1372, Pixel(true)));
      //                 ^^^^           ^^^^  ^^^^^^^^^^^
      //                 Size 1         Size 2   default Value
0 голосов
/ 29 июля 2011

Хотя я не обязательно делаю это структурой, это демонстрирует, как я бы подходил к хранению и доступу к данным. Если Pixel довольно большой, вы можете вместо этого использовать std :: deque.

struct Pixel2D {
  Pixel2D (size_t rsz_, size_t csz_) : data(rsz_*csz_), rsz(rsz_), csz(csz_) {
    for (size_t r = 0; r < rsz; r++)
    for (size_t c = 0; c < csz; c++)
      at(r, c).setOn(true);
  }
  Pixel &at(size_t row, size_t col) {return data.at(row*csz+col);}
  std::vector<Pixel> data;
  size_t rsz;
  size_t csz;
};
0 голосов
/ 29 июля 2011

Проверьте универсальную библиотеку изображений Boost.

gray8_image_t pixelArray;
pixelArray.recreate(1300,1372);
for(gray8_image_t::iterator pIt = pixelArray.begin(); pIt != pixelArray.end(); pIt++) {
    *pIt = 1;
}
0 голосов
/ 29 июля 2011

Я не уверен, насколько сложен ваш тип данных Pixel, но, возможно, что-то подобное будет работать для вас?:

std :: fill (array, array + 100, 42);// устанавливает каждое значение в массиве на 42

Ссылка: Инициализация обычного массива с одним значением по умолчанию

0 голосов
/ 29 июля 2011

Если вы хотите передать это функции, я бы проголосовал против использования простых массивов. Рассмотрим:

void doWork(Pixel array[][]);

Не содержит информации о размере. Вы можете передать информацию о размере через отдельные аргументы, но я бы предпочел использовать что-то вроде std :: vector . Конечно, для этого необходимо определить соглашение об адресации (основной ряд или основной столбец).

Альтернативой является std :: vector >, где каждый уровень векторов представляет собой одно измерение массива. Преимущество: двойной индекс, как в pixelArray [x] [y], работает, но создание такой структуры утомительно, копирование обходится дороже, потому что это происходит с отдельным экземпляром вектора, а не с простым memcpy, и векторы, содержащиеся в вектор верхнего уровня не обязательно должен иметь одинаковый размер.

Это в основном ваши варианты использования стандартной библиотеки. Правильным решением будет что-то вроде std :: vector с двумя измерениями. Вспоминаются числовые библиотеки и библиотеки манипулирования изображениями, но матрицы и классы изображений, скорее всего, ограничены примитивными типами данных в своих элементах.

РЕДАКТИРОВАТЬ: Забыл прояснить, что все выше, это только аргументы. В конце концов, ваш личный вкус и контекст должны быть приняты во внимание. Если вы сами в проекте, вектор плюс определенное и задокументированное соглашение об адресации должно быть достаточно хорошим. Но если вы в команде, и, вероятно, кто-то не примет во внимание документированное соглашение, каскадная структура вектор-вектор, вероятно, будет лучше, потому что утомительные части могут быть реализованы вспомогательными функциями.

...