How to allocate a 2D array of pointers in C++

64,661

Solution 1

By the letter of the law, here's how to do it:

// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
  array2d[i] = new (int*)[cols];
}

// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
  for (int j = 0; j < cols; ++j) {
    array2d[i][j] = NULL;
  }
}

Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.

However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.

Solution 2

It depends. It can be as simple as:

int main()
{
    int*   data[10][20]; // Fixed size known at compile time

    data[2][3] = new int(4);
}

If you want dynamic sizes at runtime you need to do some work.
But Boost has you covered:

int main()
{
   int  x;
   int  y;
   getWidthAndHeight(x,y);

   // declare a 2D array of int*
   boost::multi_array<int*,2>   data(boost::extents[x][y]);

   data[2][3] = new int(6);
}

If you are fine with jagged arrays that can grow dynamically:

int main()
{
    std::vector<std::vector<int*> >   data;

    data.push_back(std::vector<int*>(10,NULL));
    data[0][3] = new int(7);
}

Note: In all the above. I assume that the array does not own the pointer. Thus it has not been doing any management on the pointers it contains (though for brevity I have been using new int() in the examples). To do memory management correctly you need to do some more work.

Solution 3

int *pointerArray[X][Y];
int **ptrToPointerArray = pointerArray;

That's how you make a true (contiguous in memory) multidimensional array.

But realize that once you cast a multidimensional array to a pointer like that, you lose the ability to index it automatically. You would have to do the multidimensional part of the indexing manually:

int *pointerArray[8][6]; // declare array of pointers
int **ptrToPointerArray = &pointerArray[0][0]; // make a pointer to the array
int *foo = pointerArray[3][1]; // access one element in the array
int *bar = *(ptrToPointerArray + 3*8 + 1); // manually perform row-major indexing for 2d array

foo == bar; // true
int *baz = ptrToPointerArray[3][1]; // syntax error

Solution 4

You could try Boost::MultiArray.

Check out this page for details.

Solution 5

double** array = new double*[rowCnt];
for (int row = 0; row < rowCnt; ++row)
  array[row] = new double[colCnt];
for (int row = 0; row < rowCnt; ++row)
  for (int col = 0; col < colCnt; ++col)
    array[row][col] = 0;
Share:
64,661
TheFuzz
Author by

TheFuzz

Updated on August 23, 2021

Comments

  • TheFuzz
    TheFuzz almost 3 years

    I'm trying to make a pointer point to a 2D array of pointers. What is the syntax and how would I access elements?

  • Charles Salvia
    Charles Salvia over 14 years
    Also, you shouldn't inherit from STL containers
  • Crashworks
    Crashworks over 14 years
    That's more like a pointer to an array of pointers to arrays.
  • user1703401
    user1703401 over 14 years
    Maybe the array[row][col] syntax clarifies it?
  • Crashworks
    Crashworks over 14 years
    But it's still not contiguous.
  • Martin York
    Martin York over 14 years
    C++ is strongly typed conversion from int* to int** is not allowed without an explicit cast.
  • Martin York
    Martin York over 14 years
    @Crashworks: There was no requirement for the data to be contiguous.
  • Martin York
    Martin York over 14 years
    @nobugz: Still a very C like solution. The array should at least clean up itself.
  • Martin York
    Martin York over 14 years
    @Effo: This implementation has some serious bugs. Assignment operator missing. Possible double delete of pointers if used incorrectly. array_1 can be accidentally copied to a local copy and on desruction will delete a row in the array.
  • Martin York
    Martin York over 14 years
    @Charles: Shouldn't is too strong. Probably not a good idea. As the container does not have a virtual destructor. But under the write conditions (not these here) inheriting could be acceptable.
  • Crashworks
    Crashworks over 14 years
    True. However, conversion from int*[] to int**, which is what I do here, is automatic.
  • Crashworks
    Crashworks over 14 years
    It depends on what OP means by "2d array". If he simply means something that can be accessed with two subscript operators a[n][m], then yes, this is duck-typed as a multidim array. If he means what the standard specifies as a 2D array, which is a contiguous region of n*m many elements, then a 1D array of pointers to 1D arrays is not the same thing.
  • Crashworks
    Crashworks over 14 years
    @Martin, well, the standard specifies a multidimensional array as contiguous (8.3.4). So, the requirement depends on what he meant by "2D array": if he means what the C++ standard calls a 2D array, then yes, it must be contiguous. If he just means something that has two subscripts, then heck, just use a vector<vector<int *> >.
  • Test
    Test over 14 years
    @Martin York: right. I just write it to 1. present my ideas; 2. make sure the ideas will being work.
  • Drew Hall
    Drew Hall over 14 years
    @Martin York: First, the NULL assignment loop was for initialization (so we don't have a bunch of garbage pointers)--I wasn't trying to show deallocation, but mentioned in the text how to go about it. I also mentioned in my text that you'd usually wrap it in a class which would provide RAII (what I meant by "internally managed"), but I was specifically just trying to answer the direct question. I didn't touch the more metaphysical "should you even try to do this" issue... :)
  • Drew Hall
    Drew Hall over 14 years
    @Crashworks: The contiguous m*n array was what I was trying to suggest in my last paragraph--in retrospect it doesn't quite read that way but that's what I intended (hence the need to overload operator()).
  • Martin York
    Martin York over 14 years
    True: However this is not that conversion: int **ptrToPointerArray = pointerArray; Try compiling your code with a C++ compiler and you will see the error.
  • Martin York
    Martin York over 14 years
    @Drew: Sorry got the NULL part wrong. That would be great for the answer to a C question. But this is C++. I would expect to see resource management and auto-cleanup of the array itself using RAII. (Note the OP does not specify if the data in the array is owned so cleaning up of the contained pointers need not be done (but the array should be able to clean up itself)).
  • Martin York
    Martin York over 14 years
    @Crashworks: The question is quite clear on what is needed. There is no requirement of contiguous storage. Only the ability to declare and access elements.
  • Martin York
    Martin York over 14 years
    @Crashworks: Admittedly multidimensional is an overloaded term. But few people use the C standard as a definition. But the question is quite specific on requirements (non of which require contiguous elements). Yes Vector<Vector> is a solution assuming Jagged arrays are fine.
  • Crashworks
    Crashworks over 14 years
    Good grief! Bjarne just loves to make trouble. I've made the correction.