Back to July Calendar 

Previous Entry Next Entry→

September 10, 2005

I'm thinking about new and delete which perform memory allocation/deletion jobs which the old C used the dreaded functions malloc and free to do.  This is a crucial element of working with data structures such as stacks, where the exact number of objects to be created is not known at compile time

Memory for single objects can be allocated using statements (based on yesterday's Point class) such as

   a = new Point();
   b = new Point(2.0, 3.0);

Memory for an arrays of objects such as Point objects can be allocated using statements such as

    c = new Point[num_points];

The delete operator is used to release memory that has previously been allocated using new, but it's an error to use the delete operator on memory allocated by any means other than new.

The keyword new returns the starting address of the memory it has allocated, so a, b, and c must be defined as pointer types, Point *. A single object can be released using a statement such as

    delete a;

When releasing memory associated with an array, it is important to remember to use the following notation:

    delete[] c;

If the square brackets are omitted, only the first object in the array will be released, and the memory associated with the rest of the objects will be leaked.

So, you could try replacing the point_test.cpp program below:

nd_test.cpp

// Test program for the new and delete operators.
#include "point.h"
int main() {
    int num_points;
    Point *a, *b, *c;
    float d;
    // Allocate a single Point object in heap memory. 
    // This invokes the default constructor.

    a = new Point();
    // This invokes a constructor that has two arguments.
    b = new Point(2.0, 3.0);
    // Print out the two point objects.
    cout << "Here are the two Point objects I have created:" << endl;
    // Note use of arrow member selection operator here:
    a->print();
    b->print();
    // Destroy the two Point objects.
    delete a;
    delete b;
    // Now allocate an array of Point objects in heap memory.
    cout << "I will now create an array of Points. How big shall I make it? ";
    cin >> num_points;
    c = new Point[num_points];
    for (int i = 0; i < num_points; i++) {
        d = (float)i;
        c[i].set_x(d);
        c[i].set_y(d + 1.0);
    }
    // Print out the array of point objects.
    cout << "Here is the array I have created:" << endl;
    for (int i = 0; i < num_points; i++) {
        // Just for contrast, use the dot member selection operator instead of arrow
        c[i].print();
    }
    // Destroy the array of Point objects.
    delete[] c;                 // What happens if [] is omitted?
    return 0;
}

Here's the output

In constructor Point::Point()
In constructor Point::Point(float fX, float fY)
Here are the two Point objects I have created:
(0,0)
(2,3)
In destructor Point::~Point()
In destructor Point::~Point()
I will now create an array of Points. How big shall I make it? 4
In constructor Point::Point()
In constructor Point::Point()
In constructor Point::Point()
In constructor Point::Point()
Here is the array I have created:
(0,1)
(1,2)
(2,3)
(3,4)
In destructor Point::~Point()
In destructor Point::~Point()
In destructor Point::~Point()
In destructor Point::~Point()

How's that for a nifty demonstration? 

================================================================

That's one way to dynamically create an array of objects, but it may not be the best way to manage a collection of objects that is constantly changing.   To delete a single object while retaining the rest, say, you might want an array of pointers to hold individually allocated objects, as shown in the example below. Even here we need to know how big to make the pointer array. 

The better way is to use a linked list is the data structure, with no assumptions about the maximum number of objects to be stored. Later.  For now, here's an improvement on the above:
 

// pa_test.cpp
// Pointer array test program.
#include "point.h"
int main() {
   int i, max_points;
   // a will be a pointer to an array of pointers to points
  
Point **a;
   max_points = 5;
   // Create an array of pointers to Point objects. We will use the
   // array elements to hold on to dynamically allocated Point objects.
  
a = new Point *[max_points];
   // Now create some point objects and store them in the array.
   for (i = 0; i < max_points; i++)
      a[i] = new Point(i, i);
   // Let's suppose we want to eliminate the middle Point.
   i = (max_points-1) / 2;
   delete a[i];
   a[i] = NULL;
   // Print out the remaining Points.
  
for (i = 0; i < max_points; i++) {
       if (a[i])
       a[i]->print();
   }
   // Delete the remaining Points. Note that it is acceptable to pass a NULL
   // pointer to the delete operator.
  
for (i = 0; i < max_points; i++)
      delete a[i];
   // Now delete the array of pointers.
  
delete[] a;
   char gump;
   cin >> gump;
   return 0;
}

Here's the output:

In constructor Point::Point(float fX, float fY)
In constructor Point::Point(float fX, float fY)
In constructor Point::Point(float fX, float fY)
In constructor Point::Point(float fX, float fY)
In constructor Point::Point(float fX, float fY)
In destructor Point::~Point()
(0,0)
(1,1)
(3,3)
(4,4)
In destructor Point::~Point()
In destructor Point::~Point()
In destructor Point::~Point()
In destructor Point::~Point()