Search code examples
c++new-operator

2D Dynamic Allocation in C++ Using New with Spatial Locality


My apologize for asking a basic question but I really could not find a suitable answer for this. I have inherited a C++ code where a part of it has a 2D allocation function Allocate2D in the form of:

float** Allocate2D(long long sizeX, long long sizeY)
{
    float** p = new float*[sizeY];
    p[0] = new float[sizeX*sizeY];

    for (long long z = 0; z < sizeY; z++) {
        p[z] = p[0] + z * sizeX;
    }
    return ptr;
}

int main(){
    long long nX = ... ; 
    long long nY = ... ; 
    short** A = (short **)Allocate2D(nX, nY);
    // do stuff with A ...
}

I have two questions on this:

1- Is Allocate2D creating a 2D array with size sizeX x sizeY?

2- Is this common/legal/good practice to allocate a 2D short array such as A when Allocate2d is defined for float**?


Solution

    1. Yes. It does depend on what exactly you mean by "2D array". There is more than one way to create a data structure for storing data that is indexed by two dimensions. One can dereference A with two dimensions, as in A[y][x], and it will work as expected. Also, there will be a pointer in A[0] that points to a contiguous array of sizeX x sizeY floats, with the X dimension varying fastest. This is the memory layout one would also get with float B[sizeY][sizeX]. However, the types of A and B, (ignoring float vs short), are not the same. A is a pointer to an array of pointers, while B decays to a pointer to a float.

    2. No. It's not legal to cast a pointer to point to a different type. It breaks pointer aliasing rules. Also, since sizeof(float) is almost certainly not equal to sizeof(short), the arrays will be the wrong size, i.e. it will be nX*2 × nY. However, since a float* is never dereferenced into a float in what we can clearly see is the very limited lifetime of the float pointers, there will realistically not be a problem.

    So this will work, other than the array being twice as large as it should be. But turning the float pointers into short pointers is not strictly legal and it's ugly. It would be much better, and quite easy, to write a function template that gets the type correct.