Dynamic multidimensional arrays in C++

Hi,

today I had to code something like this:

  1. unsigned int var1; unsigned int var2;
  2. char **myArray = new char[var1][var2];

As you probably know, no C++ compiler is going to accept this; there will be an error about some non constant value as second array dimension. (g++ delivers: ... error: ‘numOfCols’ cannot appear in a constant-expression)

Ok, the straight forward solution would be to use a STL container, for example:

  1. std::vector< std::vector<char> >

But I'm having a special case where I really do not want to use the STL containers. Luckily enough, there's a solution:

  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. class ArrayTest{
  6. public:
  7.    ArrayTest(const unsigned int numOfRows, const unsigned int numOfCols)
  8.    {
  9.       unsigned int i, j;
  10.       this->numRows = numOfRows;
  11.       this->numCols = numOfCols;
  12.       this->mat = new char*[this->numRows];
  13.       for (i = 0; i < this->numRows; i++)
  14.       {
  15.          this->mat[i] = new char[this->numCols];
  16.          for (j = 0; j < numOfCols; j++)
  17.          {
  18.             this->mat[i][j] = (j%10) + 48;
  19.          }
  20.       }
  21.    };
  22.  
  23.    ~ArrayTest()
  24.    {
  25.       delete [] this->mat;
  26.    };
  27.  
  28.    void print()
  29.    {
  30.       unsigned int i, j;
  31.       for (i = 0; i < this->numRows; i++)
  32.       {
  33.          for (j = 0; j < this->numCols; j++)
  34.          {
  35.             cout << this->mat[i][j] << "  ";
  36.          }
  37.          cout << "\n";
  38.       }
  39.       cout << "\n";
  40.    };
  41.  
  42. private:
  43.    unsigned int numRows;
  44.    unsigned int numCols;
  45.    char ** mat;
  46. };
  47.  
  48. int main(int argc, char **argv)
  49. {
  50.    ArrayTest myObj(10,10);
  51.    myObj.print();
  52.    return(0);
  53. }

It compiles beautifully, the print looks as nice as a demo application print can but it's got a bad error: if you run it through valgrind, you'll discover a memory leak. Reading the code carefully, you'll see that it violates the rule: Call
  1. delete []

everytime you call:
  1. new []

You'll have to rewrite the destructor like this:
  1. ...
  2. ~ArrayTest()
  3. {
  4.    unsigned int i;
  5.    for (i = 0; i < this->numRows; i++) { delete [] this->mat[i]; }
  6.    delete [] this->mat;
  7. };
  8. ...

This compiles beautifully, the print looks as nice as a demo application print can and the memory leak is closed. (Ask valgrind! :-) )

Calling the

  1. new []

operator for each row isn't the nicest thing to do, using a STL container would be preferable in most situations. But if you really think you can't, this is a valid alternative as long as you craft the destructor carefully.

Bye, Simon