The Free Store and Class Arrays

You can also use the new operator to dynamically allocate arrays of objects. For example:

String *text;

text = new String[5];

There is no way to provide initializers for the elements of an array allocated with new. The default constructor is called for each element in the array.

When you deallocate an array of objects with delete, you must specify a pair of empty brackets to indicate that an array is being deleted. The consequences of using the wrong syntax are serious. For example:

delete text; // Incorrect syntax for deleting array

When the above statement is executed, the compiler treats text as a pointer to a String, so it calls the destructor for the object *text, and then it deallocates the space pointed to by text. However, text points to an entire array, not just a single object. The destructor is called only for text[0], not for the text[1] through text[4]. As a result, the character buffers allocated for those four String objects are never deallocated. This is illustrated in Figure 6.2.

If you use the correct syntax for deleting arrays, the destructor is called properly. For example:

delete [] text;

This syntax tells the compiler that text points to an array. The compiler looks up the size of the array, which was stored when the array was first allocated with new. Then the compiler calls the destructor for all the elements in the array, from text[0] to text[4]. The destructor deallocates the buffer for each of the objects in turn, and then the compiler deallocates the space pointed to by text. This is illustrated in Figure 6.3.

In earlier versions of C++, you had to specify the size of the array within the brackets when you called delete, and errors resulted if you specified a different size than that used in the call to new. In the latest version of C++, the compiler stores the sizes of all arrays allocated with new and ignores any number you specify when calling delete.

If you're using a class that has no destructor, it is possible, although inadvisable, to delete an array of objects without specifying the []. For example, since the Date class has no destructor, the following example works:

// BAD TECHNIQUE: deleting array of objects without []

// for a class that has no destructor

Date *appointments;

appointments = new Date[10];

// Use the array

delete appointments; // Same as delete [] appointments;

In this case, the compiler notices that the Date class doesn't have a destructor, so it immediately deallocates the space pointed to by appointments. Because the Date objects have no buffers attached to them, no problems result from the lack of the destructor calls.

However, you should always use the [] syntax when deleting arrays, even for classes that have no destructors. The reason is that a class may be reimplemented later on, and the new implementation could perform dynamic memory allocation and require a destructor. (For example, you might implement a class using an array, and then switch to a linked list later. The first version doesn't require a destructor, but the second version does.) If your programs assume that the class doesn't have a destructor, they might have to be modified later on. By consistently using the [] syntax whenever you delete arrays, you ensure that your programs work properly no matter how the class is implemented.