Reputation: 259
I have a two dimensional array that I've allocated dynamically using new.
The problem is I want to allocate the memory as one connected block instead of in separated pieces to increase processing speed.
Does anyone know if it's possible to do this with new, or do I have to use malloc?
Here's my code:
A = new double*[m];
for (int i=0;i<m;i++)
{
A[i]= new double[n];
}
This code causes a segmentation fault
phi = new double**[xlength];
phi[0] = new double*[xlength*ylength];
phi[0][0] = new double[xlength*ylength*tlength];
for (int i=0;i<xlength;i++)
{
for (int j=0;j<ylength;j++)
{
phi[i][j] = phi[0][0] + (ylength*i+j)*tlength;
}
phi[i] = phi[0] + ylength*i;
}
Upvotes: 2
Views: 2204
Reputation: 116078
You can allocate one big block and use it appropriately, something like this:
double* A = new double[m*n];
for (int i=0; i<m; i++) {
for (int j=0; j<n; j++) {
A[i*n+j] = <my_value>;
}
}
Instead of using new
, you can use malloc
- there is no much difference, except that new
must be released with delete
, and malloc()
released with free()
.
UPDATE1:
You can create "true" 2d array (with dimensions m
x n
):
double** A = new double*[m];
double* B = new double[m*n];
for (int i=0; i<m; i++) {
A[i] = B + n*i;
for (int j=0; j<n; j++) {
A[i][j] = <my_value>;
}
}
Just be sure to release both A
and B
in the end.
UPDATE2:
By popular request, this is how you can create "true" 3-dimensional array (with dimensions m
x n
x o
):
double*** A = new double**[m];
double** B = new double*[m*n];
double* C = new double[m*n*o];
for (int i=0; i<m; i++) {
A[i] = B + n*i;
for (int j=0; j<n; j++) {
B[n*i+j] = C + (n*i+j)*o;
for (int k=0; k<o; k++) {
A[i][j][k] = <my_value>;
}
}
}
This uses 2 relatively small "index" arrays A
and B
, and data array C
. As usual, all three should be released after use.
Extending this for more dimensions is left as an exercise for the reader.
Upvotes: 4
Reputation: 25927
Ok, if the task is to maintain a single block of memory, but keep [][] way of addressing it, I'd try a few tricks with classes. The first one is an inside proxy:
class CoordProxy
{
private:
int coordX;
int arrayWidth;
int * dataArray;
public:
CoordProxy(int * newArray, int newArrayWidth, int newCoordX)
{
coordX = newCoordX;
arrayWidth = newArrayWidth;
dataArray = newArray;
}
int & operator [](int newCoordY)
{
return (dataArray[newCoordY * arrayWidth + coordX]);
}
};
class CoordsWrapper
{
private:
int * dataArray;
int width;
int height;
public:
CoordsWrapper(int * newArray, int newWidth, int newHeight)
{
dataArray = newArray;
width = newWidth;
height = newHeight;
}
CoordProxy operator[] (int coordX)
{
return CoordProxy(dataArray, width, coordX);
}
};
int main(int argc, char * argv[])
{
int * a = new int[4 * 4];
ZeroMemory(a, 4 * 4 * sizeof(int));
CoordsWrapper w(a, 4, 4);
w[0][0] = 10;
w[0][1] = 20;
w[3][3] = 30;
std::for_each(&a[0], &a[4 * 4], [](int x) { printf("%d ", x); });
delete[] a;
}
Note, that this is not time-efficient, but extremely memory efficient: uses 4 ints and 2 pointers more than original class.
There's even nicer and a lot faster solution, but you would have to resign from [][] notation in favor of (,) notation:
class CoordsWrapper2
{
private:
int * data;
int width;
int height;
public:
CoordsWrapper2(int * newData, int newWidth, int newHeight)
{
data = newData;
width = newWidth;
height = newHeight;
}
inline int & Data(int x, int y)
{
return data[y * width + x];
}
};
int main(int argc, char * argv[])
{
int * a = new int[4 * 4];
ZeroMemory(a, 4 * 4 * sizeof(int));
CoordsWrapper2 w(a, 4, 4);
w.Data(0, 0) = 10;
w.Data(0, 1) = 20;
w.Data(3, 3) = 30;
std::for_each(&a[0], &a[4 * 4], [](int x) { printf("%d ", x); });
delete[] a;
}
Note the inline directive. It suggests the compiler to replace the method call for actual source code, which make it a little faster. This solution is even more memory efficient and a either a tiny bit less or equally time efficient as classic indexing.
Upvotes: 0
Reputation: 9691
There is nothing you can do with malloc
that you can't do with new
(though the converse doesn't hold). However if you've already allocated the memory in separate blocks, you will have to allocate new (contiguous) memory in order to get a connected block (with either malloc
or new
). The code you show allocates m
non-contiguous n
-sized blocks. To get an array with contiguous memory from this, you would need
int MN = m*n;
B = new double[MN];
for (int i=0; i<MN; ++i)
B[i] = A[ i/N ] [ i%N ];
Upvotes: 0