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 to deal with this situation.
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. 3 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 4 using std::cout; 5 using std::endl; 6 7 #include "Integer.h" 8 9 // Integer default constructor 10 Integer::Integer( int i ) 11 : value( i ) 12 { 13 cout << "Constructor for Integer " << value << endl; 14 } // end Integer constructor 15 16 // Integer destructor 17 Integer::~Integer() 18 { 19 cout << "Destructor for Integer " << value << endl; 20 } // end Integer destructor 21 22 // set Integer value 23 void Integer::setInteger( int i ) 24 { 25 value = i; 26 } // end function setInteger 27 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 4 using std::cout; 5 using std::endl; 6 7 #include 8 using std::auto_ptr; // auto_ptr class definition 9 10 #include "Integer.h" 11 12 // use auto_ptr to manipulate Integer object 13 int main() 14 { 15 cout << "Creating an auto_ptr object that points to an Integer "; 16 17 // "aim" auto_ptr at Integer object 18 auto_ptr< Integer > ptrToInteger( new Integer( 7 ) ); 19 20 cout << " Using the auto_ptr to manipulate the Integer "; 21 ptrToInteger->setInteger( 99 ); // use auto_ptr to set Integer value 22 23 // use auto_ptr to get Integer value 24 cout << "Integer after setInteger: " << ( *ptrToInteger ).getInteger() 25 return 0; 26 } // end main
|
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.
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. |