Question regarding deleting pointers to matrices

Started by
16 comments, last by Zahlman 16 years, 11 months ago
Let's say I create a pointer to a matrix of doubles, as such:

double** matrix = new double*[10];
for (int i=0; i<10; i++)
    matrix = new double[10];

Now, if I were planning to delete said pointer, would I just invoke the delete[] operator, like this?

delete [] matrix;

Or does delete[] not act recursively, causing me to do it this way:

for (int i = 0; i<10; ++i)
    delete [] matrix;

This is basically a question about how exactly delete[] operates. Thanks in advance!
I jumped in a river and what did I see? Black-eyed angels swam with me.- Thom Yorke
Advertisement
Every new call needs a matching delete, so it would be the latter, followed by the former.
Ah, that's sort of what I expected. Thanks a lot!
I jumped in a river and what did I see? Black-eyed angels swam with me.- Thom Yorke
It's also worth noting that the whole issue could be avoided with a std::vector< std::vector< double > >.
It's hacky, but there's a method that simplifies both the memory layout (potentially helping the cache) as well as the cleanup, at the cost of a messy looking initialization. The idea is to allocate all the memory in one single chunk, set up pointers of the first array to point into the rest of the buffer as if it were a series of independent arrays. Here's the basic idea, minus fancies (such as templatizing the function):
double** Allocate2DArray(unsigned int width, unsigned int height){  char* buffer = new char[sizeof(double*) * width + sizeof(double) * width * height];  double** firstDimension = reinterpret_cast<double**>(buffer);  double* secondDimension = reinterpret_cast<double*>(buffer + sizeof(double*) * width);  double** firstDimensionEnd = firstDimension + width;  while (firstDimension < firstDimensionEnd)  {    *firstDimension = secondDimension;    firstDimension += 1;    secondDimension += height;  }  return reinterpret_cast<double**>(buffer);}void Deallocate2DArray(double** array){  //Note:  I'm not sure the reinterpret_cast back into what the  //array was allocated as is necessary, but I'm doing it just to  //be safe.  delete [] reinterpret_cast<char*>(array);}int main(){  double** array= Allocate2DArray(4, 3);  array[0][0] = 5.0;  array[3][2] = 7.0;  //etc.  Deallocate2DArray(array);}

Now I'm more inclined to encourage the method that I'm pretty confident is used by Boost::MultiArray, which is to just allocate an ordinary single-dimension array, wrap it up in a class, and then do the appropriate multiplications and additions within the subscript operator's ([]) body. (Or even better, just use Boost::MultiArray itself!) However, the method above does have the benefit of requiring no multiplications, at the cost of a little bit extra memory for the first dimension array of pointers. In some cases this might be better, but I wouldn't be surprised if it wasn't. Wrapping all this up in a class also has plenty of other benefits, such as being able to store the size/shape of the multi-dimensioned array.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
I had considered both of your alternatives, and, as logical and good as they are, I'm focusing on practicing low-level C++ programming with this project. I guarantee, though, were it for any other project, I would definitely opt for a more intuitive approach.

Thanks, guys!
I jumped in a river and what did I see? Black-eyed angels swam with me.- Thom Yorke
I also would have to sugest something more like
class matrix{ int width, int height double *storage;public: matrix ( int w, int h } : width(w), height(h) { storage = new double[width * height]; } ~matrix ( ) { delete[] storage; } double get ( int x, int y ) { return storage[x + y*height]; } void set ( int x, int y, double v ) { storage[x + y*height] = v; } double *at ( int x, int y ) { return &storage[x+y*height]; }};
I would second the suggestion of a 2D interface to a 1D array, as KulSeran suggested. I would advise against the vector-of-vectors approach, because a vector-of-vectors is jagged, not rectangular.

Finally, consider boost::array or boost::multi_array. Your claims about wanting a "low level" approach make me suspicious; it sounds like you think doing things yourself in an ugly fashion would be "faster" than using an clean, sane interface, and this is most likely blatantly untrue; it's probably also destabilizing your program.
Quote:Original post by Agony
*** Source Snippet Removed ***


Your code potentially has alignment issues. Ideally, you should use ::operator new(size) to allocate your memory, and then place the array of doubles before the array of pointers to rows.

Quote:Original post by CrimsonMemory
I had considered both of your alternatives, and, as logical and good as they are, I'm focusing on practicing low-level C++ programming with this project. I guarantee, though, were it for any other project, I would definitely opt for a more intuitive approach.


I would argue you're not practicing low-level C++ programming, you're practicing low-level C programming.

If you wanted to be programming in C++, you would be using std::valarray for this stuff. If you really wanted to be doing low-level C++ programming, you would be specializing std::valarray.

--smw

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement