Main Page

Previous Page
Next Page

[Page 829 (continued)]

16.12. Class auto_ptr and Dynamic Memory Allocation

A common programming practice is to allocate dynamic memory, assign the address of that memory to a pointer, use the pointer to manipulate the memory and deallocate the memory with delete when the memory is no longer needed. If an exception occurs after successful memory allocation but before the delete statement executes, a memory leak could occur. The C++ standard provides class template auto_ptr in header file <memory> to deal with this situation.

[Page 830]

An object of class auto_ptr maintains a pointer to dynamically allocated memory. When an auto_ptr object destructor is called (for example, when an auto_ptr object goes out of scope), it performs a delete operation on its pointer data member. Class template auto_ptr provides overloaded operators * and -> so that an auto_ptr object can be used just as a regular pointer variable is. Figure 16.10 demonstrates an auto_ptr object that points to a dynamically allocated object of class Integer (Figs. 16.816.9).

Figure 16.8. Class Integer definition.

 1  // Fig. 16.8: Integer.h
 2  // Integer class definition.
 4  class Integer
 5  {
 6  public:
 7     Integer( int i = 0 ); // Integer default constructor
 8     ~Integer(); // Integer destructor
 9     void setInteger( int i ); // functions to set Integer
10     int getInteger() const; // function to return Integer
11  private:
12     int value;
13  }; // end class Integer

Figure 16.9. Member function definition of class Integer.
(This item is displayed on pages 830 - 831 in the print version)

 1  // Fig. 16.9: Integer.cpp
 2  // Integer member function definition.
 3  #include <iostream>
 4  using std::cout;
 5  using std::endl;
 7  #include "Integer.h"
 9  // Integer default constructor
10  Integer::Integer( int i )
11     : value( i )
12  {
13     cout << "Constructor for Integer " << value << endl;
14  } // end Integer constructor
16  // Integer destructor
17  Integer::~Integer()
18  {
19     cout << "Destructor for Integer " << value << endl;
20  } // end Integer destructor
22  // set Integer value
23  void Integer::setInteger( int i )
24  {
25     value = i;
26  } // end function setInteger
28  // return Integer value
29  int Integer::getInteger() const
30  {
31     return value;
32  } // end function getInteger

Figure 16.10. auto_ptr object manages dynamically allocated memory.
(This item is displayed on pages 831 - 832 in the print version)

 1  // Fig. 16.10: Fig16_10.cpp
 2  // Demonstrating auto_ptr.
 3  #include <iostream>
 4  using std::cout;
 5  using std::endl;
 7  #include <memory>   
 8  using std::auto_ptr; // auto_ptr class definition
10  #include "Integer.h"
12  // use auto_ptr to manipulate Integer object
13  int main()
14  {
15     cout << "Creating an auto_ptr object that points to an Integer\n";
17     // "aim" auto_ptr at Integer object                  
18     auto_ptr< Integer > ptrToInteger( new Integer( 7 ) );
20     cout << "\nUsing the auto_ptr to manipulate the Integer\n";
21     ptrToInteger->setInteger( 99 ); // use auto_ptr to set Integer value
23     // use auto_ptr to get Integer value
24     cout << "Integer after setInteger: " << ( *ptrToInteger ).getInteger()
25     return 0;
26  } // end main

 Creating an auto_ptr object that points to an Integer
 Constructor for Integer 7

 Using the auto_ptr to manipulate the Integer
 Integer after setInteger: 99

 Terminating program
 Destructor for Integer 99

Line 18 of Fig. 16.10 creates auto_ptr object ptrToInteger and initializes it with a pointer to a dynamically allocated Integer object that contains the value 7. Line 21 uses the auto_ptr overloaded -> operator to invoke function setInteger on the Integer object pointed to by ptrToInteger. Line 24 uses the auto_ptr overloaded * operator to dereference ptrToInteger, then uses the dot (.) operator to invoke function getInteger on the Integer object pointed to by ptrToInteger. Like a regular pointer, an auto_ptr's -> and * overloaded operators can be used to access the object to which the auto_ptr points.

Because ptrToInteger is a local automatic variable in main, ptrToInteger is destroyed when main terminates. The auto_ptr destructor forces a delete of the Integer object pointed to by ptrToInteger, which in turn calls the Integer class destructor. The memory that Integer occupies is released, regardless of how control leaves the block (e.g., by a return statement or by an exception). Most importantly, using this technique can prevent memory leaks. For example, suppose a function returns a pointer aimed at some object. Unfortunately, the function caller that receives this pointer might not delete the object, thus resulting in a memory leak. However, if the function returns an auto_ptr to the object, the object will be deleted automatically when the auto_ptr object's destructor gets called.

[Page 832]

An auto_ptr can pass ownership of the dynamic memory it manages via its overloaded assignment operator or copy constructor. The last auto_ptr object that maintains the pointer to the dynamic memory will delete the memory. This makes auto_ptr an ideal mechanism for returning dynamically allocated memory to client code. When the auto_ptr goes out of scope in the client code, the auto_ptr's destructor deletes the dynamic memory.

Software Engineering Observation 16.9

An auto_ptr has restrictions on certain operations. For example, an auto_ptr cannot point to an array or a standard-container class.

Previous Page
Next Page