views:

902

answers:

4

how do I make a pointer to a multidimensional array, which have a unknown size? I've tried this:

int **triangles;

triangles = new int[numTriangles][3];

But i get this error:

cannot convert 'int (*)[3]' to 'int**' in assignment

+4  A: 
triangles = new int[numTriangles*3];

Then access it as:

triangles[numTriangles*triangleIndex+vertexIndex] = blah;

But this is tedious and error prone so I suggest using boost.multi_array instead, or rolling your own (really simple):

template<class T>
class Matrix {
public:
 Matrix(int _w, int _h) : data(_w*_h), w(_w), h(_h) {
 }

 T      & operator()(int x, int y)       { return data[y * w + x]; }
 T const& operator()(int x, int y) const { return data[y * w + x]; }

private:
 std::vector<T> data;
 int w, h;
};

// usage:
int main() {
    Matrix<float> triangles(numTriangles, 3);
    triangles(triangleIndex, vertexIndex) = blah;
}

If, on the other hand, you actually want an array of triangles, rather than a twodimensional array, just use a vector<Triangle> where Triangle is a class :)

Thanks, I think I'll use the first example, trying to keep things at simple as possible ;)
Xunil
Oh as soon as you actually start coding this way, it'll get horribly complicated ;)
Yes, if you ant simple go for the one of the other suggestions.
Ed Swangren
A: 

Multidimensional arrays in c++ are just syntactic sugar.

int a[n][m];

is equivalent to

int a[n*m];

so you just need a regular pointer - i.e.:

int *triangles;
triangles = new int[numTriangles*3];
KenE
+4  A: 

Well, the error message says it :) If you 'new an array, then new returns a pointer to its first element.

A multidimensional array is just another name for an array of arrays. You 'newed an array of int[3], and precisely numTriangles elements of those. So what new does is returning a pointer to int[3]. The variable you assign the result to has to have that type, which is a pointer to an array of 3 integers:

int (*triangles)[3];
triangles = new int[numTriangles][3];
triangles[triangleIndex][vertexIndex] = 42;

Of course, typedefs also help here:

typedef int triangles_t[3];
triangles_t * triangles = new int[numTriangles][3];

The parentheses are needed because of the C++ precedence rules. They tell the compiler that it's not creating an array of three pointers to integers, but a pointer to an array of 3 integers. This is similar to the more common use on function pointers ("void (*funptr)()")...

Johannes Schaub - litb
I was trying to remember how to do it the way you do in your answer (with casting), but couldn't remember before you posted. Iraimbilanja's templates and your methods are probably the best choices. Mine is probably the closest to answering the question exactly as asked.
Scottie T
Hmm casting? i dont see casting :)
I meant the (*triangles)[3]; Not sure what you'd call that.
Scottie T
Scottie, it's not a cast but it is binding the "*" to the identifier "triangles" rather than to the type "int". i explained it in the last sentence . it's because of the precedence rules in C++ you need those parentheses
Johannes Schaub - litb
first i thought you wanted to say you did it with casting to archive the same what i did without casting, so i didn't comment on your comment :p but it appears you think the "(*triangles)[3]" is executing a cast actually :) you may have seen it also when defining function pointers: void (*funptr)();
Johannes Schaub - litb
+4  A: 

To do this, you will have to loop over one dimension and allocate space for the other dimension:

int** triangles;
triangles = new int*[NUMROWS];

for (int i = 0; i < NUMROWS; i++) {
   triangles[i] = new int[NUMCOLS];
}

But be careful when doing it this way, you'll have to do the same to deallocate the memory.

for (int i = 0; i < NUMROWS; i++) {
   delete [] triangles[i];
   triangles[i] = 0;
}
delete [] triangles;
triangles = 0;
Scottie T
i would not say this is how he "does" it. He's allocating a multidimensional array (an array of arrays) in one go. those memory are contiguous and can also be freed in one go. yours is allocating an array of pointers, making those point to unrelated memory. It's different. u should mention that.
Johannes Schaub - litb