If you use [] in a new expression, use [] in the corresponding delete expression; If not, no [] in the matching delete expression.
When employing a new expression, two things happen:
- membory is allocated (via the function
operator new, item 49, 51) - one or more constructors are called for that memory
When a delete is used, two other things happen:
- one or more destructors are called for the memory
- The memory is deallocated (via the function
operator delete, item 51)
The fact is that the memory layout for single objects is generally different from the memory layout for arrays, and the memory for an array usually includes extra area for the size of the array (making it easier for delete to know how many destructor to call) while memory for a single object lacks this information:
| Memory type | Memory layout |
|---|---|
| Array | |n|Object|Object|Object|…| |
| Single object | |Object| |
When we use delete on a pointer, delete [] will assumes an array is pointed to, otherwise it assumes a single object. Let’s see what will happen if the uses of new and delete is not matching:
|
|
-
delete [] stringPtr1;The result is undefined.
deletewill read some memory and interpret what it read as an array size, then start invoking the destructors, and it’s probably not holding the objects of the type it’s busy destructing at this point. -
delete stringPtr2;It’s undefined behavior too. It’s easy to see the expression would lead to too few destructors being called. Furthermore, it’s also undefined for built-in types (which lack destructors), too.
The rule is particularly important to bear in mind when writing a class containing a pointer to dynamically allocated memory and also offering multiple constructors, for we must be careful to use the same form of new in all the constructors to initialize the pointer member. After all, there’s only one form of delete in the destructor.
The rule is also noteworthy for typedef-inclined:
|
|
To avoid such confusion, abstain from typedefs for array types. Try using string and vector from the standard C++ library (item 54) - those templates reduce the need for dynamically allocated arrays to nearly zero: for example, we may define AddressLines as type vector<string>.