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.7–17.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
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
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
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.