Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allocate contiguous memory for a 3D array in C++

I'm able to allocate contiguous memory to allocate a 2D array in C++. I do not know how to do for a 3D array. I have already read some posts but I haven't been able to come up with a solution.

#include <iostream>


using namespace std;

int main(int argc, char **argv){
    cout << "Ints have size " << sizeof(int) << endl;

int rows= 2;
int cols= 3;

int **i= new int*[rows];
int size= rows*cols;
i[0]= new int[size];
for(int j= 1; j < rows; j++) {
  i[j]= &i[0][j*cols];
}

for(int j= 0; j < rows; j++) {
  for(int k= 0; k < cols; k++) {
    cout << j << " " << k << " " << &i[j][k] << endl;
  }
}
delete[] i;
return 0;
}
like image 266
Marco Avatar asked Dec 13 '22 10:12

Marco


1 Answers

A 3d array with P planes, each of which has R rows and C columns will require P*R*C elements. You can just allocate them at once for example with:

Element *p = new Element[P*R*C];

then to access the element at coordinates (p, r, c) you can use as formula:

int index = (p*R + r)*C + c;

To make things readable an easy solution is to make a class

template<typename T>
struct Matrix3D {
    int P, R, C;
    std::vector<T> elements;

    Matrix3D(int P, int R, int C)
        : P(P), R(R), C(C), elements(P*R*C)
    { }

    T& operator()(int p, int r, int c) {
        return elements[(p*R + r)*C + c];
    }
};

in this example I'm using an std::vector to store the elements because this makes things simpler about ownership/copying and still guarantees all elements will be contiguous in memory. If you want to manually allocate the storage then more code is needed.

If the size is known at compile time then you can make P, R and C template parameters and use an std::array member instead of std::vector. This should give some performance improvement as the whole class will end up being a single chunk of memory in the heap and allowing constant multiplication tricks for element access.

like image 147
6502 Avatar answered Dec 16 '22 00:12

6502