17.9. Class unique_ptr and Dynamic Memory Allocation

Image

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. C++11 provides class template unique_ptr in header <memory> to deal with this situation.

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


 1   // Fig. 17.7: 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 ); // set Integer value
10      int getInteger() const; // return Integer value
11   private:
12      int value;
13   }; // end class Integer


Fig. 17.7. Integer class definition.


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


Fig. 17.8. Member function definitions of class Integer.

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


 1   // Fig. 17.9: fig17_09.cpp
 2   // Demonstrating unique_ptr.
 3   #include <iostream>
 4   #include <memory>
 5   using namespace std;
 6
 7   #include "Integer.h"
 8
 9   // use unique_ptr to manipulate Integer object
10   int main()
11   {
12      cout << "Creating a unique_ptr object that points to an Integer ";
13
14      // "aim" unique_ptr at Integer object                  
15      unique_ptr< Integer > ptrToInteger( new Integer( 7 ) );
16
17      cout << " Using the unique_ptr to manipulate the Integer ";
18      ptrToInteger->setInteger( 99 ); // use unique_ptr to set Integer value
19
20      // use unique_ptr to get Integer value
21      cout << "Integer after setInteger: " << ( *ptrToInteger ).getInteger()
22         << " Terminating program" << endl;
23   } // end main


Creating a unique_ptr object that points to an Integer
Constructor for Integer 7

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

Terminating program
Destructor for Integer 99


Fig. 17.9. unique_ptr object manages dynamically allocated memory.

Because ptrToInteger is a local automatic variable in main, ptrToInteger is destroyed when main terminates. The unique_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 a unique_ptr to the object, the object will be deleted automatically when the unique_ptr object’s destructor gets called.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.135.81