How to allocate a 2D array of pointers in C++
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;
TheFuzz
Updated on August 23, 2021Comments
-
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 over 14 yearsAlso, you shouldn't inherit from STL containers
-
Crashworks over 14 yearsThat's more like a pointer to an array of pointers to arrays.
-
user1703401 over 14 yearsMaybe the array[row][col] syntax clarifies it?
-
Crashworks over 14 yearsBut it's still not contiguous.
-
Martin York over 14 yearsC++ is strongly typed conversion from int* to int** is not allowed without an explicit cast.
-
Martin York over 14 years@Crashworks: There was no requirement for the data to be contiguous.
-
Martin York over 14 years@nobugz: Still a very C like solution. The array should at least clean up itself.
-
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 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 over 14 yearsTrue. However, conversion from int*[] to int**, which is what I do here, is automatic.
-
Crashworks over 14 yearsIt 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 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 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 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 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 over 14 yearsTrue: 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 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 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 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 over 14 yearsGood grief! Bjarne just loves to make trouble. I've made the correction.