[Solved] Why does the top code work and the bottom code not in c++ for dynamic matrix allocation? [closed]


Remarks:

  • You do not free allocated memory by using delete[]. That’s a very bad practice. You always should remember to free memory you allocated.

  • It is very, very uncomfortable to choose jagged arrays (arrays of arrays) for long term use. A lot easier solution is to allocate a single array:

    double * phi = new double[xlength * ylength];
    

    And then access (x, y)-th element as following:

    phy[y * xlength + x] = 20.0;
    

    The allocation takes less time, you have a lot less things to free (only the phi itself) and access time is more-less equally fast.

  • Consider using std::vector or std::array. Since you use C++ and not C, the natural way is to use these containers instead of raw arrays, they are a lot more managable and they care themselves to free their contents if allocated statically. In your case it would look like:

    #include <vector>
    
    (...)
    
    std::vector<std::vector<double> > phi;
    
    phi.resize(xlength);
    for (int x = 0; x < xlength; x++)
        phi[x].resize(ylength);
    

Solution:

Your solution won’t work. The reason, why author of the original code uses three variables is, that one of them has to contain the actual data and two others serve as pointers to parts of the original data.

In your case, you try to keep both the data and pointers to parts of the data in the same array, what simply cannot work. If you want the [][][] notation, you have to allocate jagged arrays in nested loops, just as I’ve shown in my solution. On the other hand, if you want one array to keep single block of data and another to keep pointers, you’ll have to do it as author of the first piece of code did.


It took me a few minutes of time to figure out, how the three-dimensional solution with three variables actually work, so I’ll leave an explanation for everyone, who’ll encounter this thread.

The general idea is to have one variable with actual data and two proxy variables with a set of pointers, which allows addressing the actual data with [][][] notation.

C contains the actual data, so it is of size [zDim * yDim * xDim]. You can access (x, y, z) element by addressing it by [z * xDim * yDim + y * xDim + x]. [][][] notation means, that the data is organized by slices (z), which contains rows (y), which contains elements(x).

You construct array B containing pointers to all rows, ordered by slice. So B contains: (slice 0, row 0), (slice 0, row 1), ..., (slice 0, row yDim - 1), (slice 1, row 0), ...

Then, you construct array A containing pointers to elements of array B, such that z-th element of A points to (z * yDim) = 0-th row of z-th slice. Finally, when you address the array A, it works like following:

  • A[z] contains address to element of array B containing pointer to 0th row of zth slice
  • A[z][y] moves this pointer, such that now we have actual pointer to 0-th element of y-th row of z-th slice.
  • Finally, A[z][y][x] shifts us by x elements, such that we receive x-th element of y-th row of z-th slice.

Now it should be clear, why you need additional variables and why it cannot be done with only single variable.

Bottomline: never use such solution, its a huge waste of memory. Instead, flatten your arrays and address by [z * xDim * yDim + y * xDim + x] or use jagged std::vectors or std::arrays.

23

solved Why does the top code work and the bottom code not in c++ for dynamic matrix allocation? [closed]