Многомерные массивы C++ на "куче"

22
задан Garrett 9 November 2014 в 23:36
поделиться

10 ответов

Если Вы уже знаете размер вложенных размеров, можно также буквально выделить многомерный массив, использующий новый:

typedef int dimensions[3][4];

dimensions * dim = new dimensions[10];
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42;
delete [] dim;

вместо 10, время выполнения определенное значение может быть передано. Так как это не часть оператора типа новые возвраты, это позволяется. Это хорошо, если Вы знаете число столбцов, но хотите сохранить количество переменной строк, например. Определение типа облегчает читать код.

24
ответ дан Johannes Schaub - litb 29 November 2019 в 04:02
поделиться

Для полноты картины, вот лучший способ сделать это в C ++, когда вы знаете границы массива заранее. Преимущество использования следующего класса заключается в том, что вам не нужно заботиться о вызове delete [] для ваших данных. Это означает, что этот класс будет безопасным для исключений, и все другие замечательные вещи о RAII .

template<typename T, int width, int height>
class MultiArray
{
    private:
        typedef T cols[height];
        cols * data;
    public:
        T& operator() (int x, int y) { return data[x][y]; }
        MultiArray() { data = new cols[width]; }
        ~MultiArray() { delete [] data; }
};

Использование:

MultiArray<int, 10, 10> myArray;
myArray(2, 3) = 4;
cout << myArray(2, 3);

Редактирование: , и, пока я в этом, вот настройка, которую вы можете использовать, если вы не знать границы массива до времени выполнения:

template<typename T>
class Array2D
{
    private:
        const int width;
        T * data;
    public:
        T& operator() (int x, int y) { return data[y*width + x]; }
        Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
        ~Array2D() { delete [] data; }
};

Использование:

Array2D myArray(10, 10);
myArray(3, 4) = 42;
cout << myArray(3, 4);
6
ответ дан e.James 29 November 2019 в 04:02
поделиться

Как насчет того, чтобы использовать Повышение. Мультимассив? Я полагаю, что это отвечает на Вашу потребность вполне хорошо! http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html#sec_introduction

Вот выборка от страницы документации:

 #include < boost/multi_array.hpp >

 #include < cassert >

int main () 

{

  // Create a 3D array that is 3 x 4 x 2

  typedef boost::multi_array< double, 3 > array_type;

  typedef array_type::index index;

  array_type A(boost::extents[3][4][2]);


  // Assign values to the elements

  int values = 0;

  for(index i = 0; i != 3; ++i) 

    for(index j = 0; j != 4; ++j)

      for(index k = 0; k != 2; ++k)

        A[i][j][k] = values++;

  // Verify values

  int verify = 0;

  for(index i = 0; i != 3; ++i) 

    for(index j = 0; j != 4; ++j)

      for(index k = 0; k != 2; ++k)

        assert(A[i][j][k] == verify++);

  return 0;

}
6
ответ дан Benoît 29 November 2019 в 04:02
поделиться

std::vector<std::vector<int> > должен быть упомянут, поскольку это часто - самый простой путь. Однако знайте, что это является непрямоугольным. Не каждый std::vector<int> потребности иметь ту же длину.

3
ответ дан MSalters 29 November 2019 в 04:02
поделиться

Посмотрите это: FAQ C++ Marshall Cline

Видит, "Как я выделяю многомерные массивы, использующие новый?" и, "Но предыдущий код FAQ’s SOOOO хитрый и подверженный ошибкам! Isn’t там более простой путь?" разделы.

6
ответ дан seaotternerd 29 November 2019 в 04:02
поделиться

Я удивлен, что никто еще не упомянул boost::multi_array. Я нуждался в 2D массиве в программе только на прошлой неделе и нашел, что он был намного легче, и более быстрым для кодирования, чем варившие домом решения, которые я предложил прежде (все из которых упоминаются в других комментариях).

3
ответ дан Head Geek 29 November 2019 в 04:02
поделиться

Вот реализация, которую я имею; я объявляю единственный непрерывный блок int с вместо того, чтобы создать новые блоки в моем для цикла, таким образом, я не вызываю отсутствия страницы повсеместно. Благодаря eJames для указания, почему этот код был поврежден первоначально.

int width = 10, height = 10, totalSize = width*height;
int **myArray = new int*[width];
int *data = new int[totalSize];

for ( int i = 0; i < height; ++i )
{
    myArray[i] = data + (i*width);
}

// do some things here

delete[] data;
delete[] myArray;
3
ответ дан eplawless 29 November 2019 в 04:02
поделиться

Как другая альтернатива, STLSoft включает класс fixed_array_2d (а также 3D и 4D версии). По сравнению с homebrewed решениями, данными здесь, это имеет подобную реализацию, но более полный набор функций (полная поддержка итераторов, и т.д.). По сравнению с повышением:: multi_array, это - более легкий вес и легче на не совсем совместимых компиляторах C++, но (намеренно) испытывает недостаток в некоторых функциях multi_array.

2
ответ дан Josh Kelley 29 November 2019 в 04:02
поделиться

Ваш цикл не будет правильно записывать значения указателя в myArray. Я бы предложил следующее:

int width = 10;
int height = 10;
int ** myArray = new int*[width];
int * data = new int[width*height];
int * index = data;
for (int i = 0; i < width; i++)
{
    myArray[i] = index;
    index += height;
}

// ...

delete[] data;
delete[] myArray;
2
ответ дан e.James 29 November 2019 в 04:02
поделиться

Можно индексировать одномерное как 2, 3, или размерный N, если Вы просто располагаете с интервалами по корректной сумме элементов. Например, если у меня есть 10 строк и 10 столбцов, я знаю, что, если я нахожусь на строке 3, я должен буду пробежаться по крайней мере через 30 элементов для получения до нее.

Так или иначе я предпочитаю эту нотацию для простых 2D массивов, так как я не должен волноваться о вложенных уровнях указателей. Оборотная сторона является более грязной индексной нотацией. Вот пример с 2D массивом с n строками и m столбцами:

int *matrix = new int[n*m];

//set element (3,7) to 10
matrix[3*m+7] = 10;

//print the matrix
for (int i = 0; i < n; i++) {
  for (int j = 0; j < m; j++) {
    cout << matrix[i*m+j] << ' ';
  }
  cout << '\n';
}
0
ответ дан Rich 29 November 2019 в 04:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: