Dynamic Memory Management with Operators new and delete

C++ enables programmers to control the allocation and deallocation of memory in a program for any built-in or user-defined type. This is known as dynamic memory management and is performed with operators new and delete. Recall that class Employee (Figs. 10.1210.13) uses two 25-character arrays to represent the first and last name of an Employee. The Employee class definition (Fig. 10.12) must specify the number of elements in each of these arrays when it declares them as data members, because the size of the data members dictates the amount of memory required to store an Employee object. As we discussed earlier, these arrays may waste space for names shorter than 24 characters. Also, names longer than 24 characters must be truncated to fit in these fixed-size arrays.

Wouldn't it be nice if we could use arrays containing exactly the number of elements needed to store an Employee's first and last name? Dynamic memory management allows us to do exactly that. As you will see in the example of Section 10.7, if we replace array data members firstName and lastName with pointers to char, we can use the new operator to dynamically allocate (i.e., reserve) the exact amount of memory required to hold each name at execution time. Dynamically allocating memory in this fashion causes an array (or any other built-in or user-defined type) to be created in the free store (sometimes called the heap)a region of memory assigned to each program for storing objects created at execution time. Once the memory for an array is allocated in the free store, we can gain access to it by aiming a pointer at the first element of the array. When we no longer need the array, we can return the memory to the free store by using the delete operator to deallocate (i.e., release) the memory, which can then be reused by future new operations.


Again, we present the modified Employee class as described here in the example of Section 10.7. First, we present the details of using the new and delete operators to dynamically allocate memory to store objects, fundamental types and arrays.

Consider the following declaration and statement:

Time *timePtr;
timePtr = new Time;

The new operator allocates storage of the proper size for an object of type Time, calls the default constructor to initialize the object and returns a pointer of the type specified to the right of the new operator (i.e., a Time *). Note that new can be used to dynamically allocate any fundamental type (such as int or double) or class type. If new is unable to find sufficient space in memory for the object, it indicates that an error occurred by "throwing an exception." Chapter 16, Exception Handling, discusses how to deal with new failures in the context of the ANSI/ISO C++ standard. In particular, we will show how to "catch" the exception thrown by new and deal with it. When a program does not "catch" an exception, the program terminates immediately. [Note: The new operator returns a 0 pointer in versions of C++ prior to the ANSI/ISO standard. We use the standard version of operator new throughout this book.]

To destroy a dynamically allocated object and free the space for the object, use the delete operator as follows:

delete timePtr;

This statement first calls the destructor for the object to which timePtr points, then deallocates the memory associated with the object. After the preceding statement, the memory can be reused by the system to allocate other objects.

Common Programming Error 10.8

Not releasing dynamically allocated memory when it is no longer needed can cause the system to run out of memory prematurely. This is sometimes called a "memory leak."

C++ allows you to provide an initializer for a newly created fundamental-type variable, as in

double *ptr = new double( 3.14159 );

which initializes a newly created double to 3.14159 and assigns the resulting pointer to ptr. The same syntax can be used to specify a comma-separated list of arguments to the constructor of an object. For example,


Time *timePtr = new Time( 12, 45, 0 );

initializes a newly created Time object to 12:45 PM and assigns the resulting pointer to timePtr.

As discussed earlier, the new operator can be used to allocate arrays dynamically. For example, a 10-element integer array can be allocated and assigned to gradesArray as follows:

int *gradesArray = new int[ 10 ];

which declares pointer gradesArray and assigns it a pointer to the first element of a dynamically allocated 10-element array of integers. Recall that the size of an array created at compile time must be specified using a constant integral expression. However, the size of a dynamically allocated array can be specified using any integral expression that can be evaluated at execution time. Also note that, when allocating an array of objects dynamically, the programmer cannot pass arguments to each object's constructor. Instead, each object in the array is initialized by its default constructor. To delete the dynamically allocated array to which gradesArray points, use the statement

delete [] gradesArray;

The preceding statement deallocates the array to which gradesArray points. If the pointer in the preceding statement points to an array of objects, the statement first calls the destructor for every object in the array, then deallocates the memory. If the preceding statement did not include the square brackets ([]) and gradesArray pointed to an array of objects, only the first object in the array would receive a destructor call.

Common Programming Error 10.9

Using delete instead of delete [] for arrays of objects can lead to runtime logic errors. To ensure that every object in the array receives a destructor call, always delete memory allocated as an array with operator delete []. Similarly, always delete memory allocated as an individual element with operator delete.


Introduction to Computers, the Internet and World Wide Web

Introduction to C++ Programming

Introduction to Classes and Objects

Control Statements: Part 1

Control Statements: Part 2

Functions and an Introduction to Recursion

Arrays and Vectors

Pointers and Pointer-Based Strings

Classes: A Deeper Look, Part 1

Classes: A Deeper Look, Part 2

Operator Overloading; String and Array Objects

Object-Oriented Programming: Inheritance

Object-Oriented Programming: Polymorphism

Templates

Stream Input/Output

Exception Handling

File Processing

Class string and String Stream Processing

Web Programming

Searching and Sorting

Data Structures

Bits, Characters, C-Strings and structs

Standard Template Library (STL)

Other Topics

Appendix A. Operator Precedence and Associativity Chart

Appendix B. ASCII Character Set

Appendix C. Fundamental Types

Appendix D. Number Systems

Appendix E. C Legacy Code Topics

Appendix F. Preprocessor

Appendix G. ATM Case Study Code

Appendix H. UML 2: Additional Diagram Types

Appendix I. C++ Internet and Web Resources

Appendix J. Introduction to XHTML

Appendix K. XHTML Special Characters

Appendix L. Using the Visual Studio .NET Debugger

Appendix M. Using the GNU C++ Debugger

Bibliography



C++ How to Program
C++ How to Program (5th Edition)
ISBN: 0131857576
EAN: 2147483647
Year: 2004
Pages: 627

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net