Rogue Wave banner
Previous fileTop of DocumentContentsIndexNext file

7.5 Using the Smart Pointer Classes

In addition to the handle-body and singleton patterns, the Smart Pointer package contains three lower-level smart pointer classes that you can use to create your own higher-level abstractions. These template classes all provide exception-safe dynamic memory allocation. In addition:

Each of these classes is an abstraction that simplifies the use of pointers referring to objects on the heap. The pointed-to object is called the pointer's body. The pointer class's Body template parameter specifies the type of object to which this pointer can refer.

7.5.1 Using RWTOnlyPointer

RWTOnlyPointer is useful for reclaiming dynamically allocated memory, especially when the block of code in which the memory is allocated may exit prematurely due to an exception being thrown. By wrapping a raw pointer in an RWTOnlyPointer object, you can depend on the smart pointer's destructor to delete the raw pointer when the exception causes the stack to unwind. This is an example of the "resource acquisition is initialization" technique described by Stroustrup in The C++ Programming Language (see the bibliography).

This class implements strict ownership semantics, so that only one RWTOnlyPointer can own a particular body at a given time. If the assignment operator or the copy constructor is called, then the right-hand instance is invalidated (its body pointer is set to NULL), and the left-hand instance assumes responsibility for deleting the body. Thus RWTOnlyPointer is best for local protection of dynamic memory; it is not suitable for sharing pointers among several objects. Sharing pointers can be accomplished with RWTCountingPointer and RWTCountedPointer, as described in Section 7.5.2 and Section 7.5.3, respectively.

To see why RWTOnlyPointer is useful, consider Example 64.

Example 64 -- Allocating memory with a potential memory leak

If initialize() throws an exception, the allocated memory is not released. You can fix the memory leak problem by using RWTOnlyPointer, as shown in Example 65.

Example 65 -- Using a smart pointer to reclaim memory

//1The RWTOnlyPointer instance member is constructed. The allocated int is deleted automatically if an exception occurs inside initialize().

Keep in mind that the copy construction and assignment semantics of RWTOnlyPointer modify the right-hand instance so that it doesn't point to the body anymore. So, for example:

Example 66 -- Mistakenly using an invalid pointer

//1p1 points to the integer 10 stored on the heap.
//2p1 is invalidated.
//3Because p1 is not valid, the dereferencing operation throws an RWTHRInvalidPointer exception. The memory pointed to by p2 is automatically deleted.

7.5.2 Using RWTCountedPointer

RWTCountedPointer is a smart pointer template class that acts as a handle to a reference-counting body. Each time an instance of this class is bound to a body instance, it increments the reference-count maintained by that body. Each time an instance of this class detaches from a body instance, it decrements the body's reference-count and, if there are no more references, deletes the body instance. The reference-counting relieves clients of the burden of tracking whether it is safe to delete a body instance.

The class specified as the Body parameter to RWTCountedPointer must provide:

The Body has the responsibility to maintain the reference-count, usually by containing an attribute member of type unsigned.

7.5.2.1 Deriving from RWTCountingBody for Reference Counting

An easy way to provide these requirements is to derive the body class from the RWTCountingBody helper class. RWTCountingBody expects a mutex type as its template parameter. The mutex ensures that the reference counting is thread-safe.

Example 67 shows the use of RWTCountedPointer with a template parameter of class Foo, which is derived from RWTCountingBody. See examples\thr0200osfam\pointer\RWTCountedPointerEx.cpp for the full example.

Example 67 -- Providing reference counting for a counted pointer

//1Foo inherits from the RWTCountingBody<RWMutexLock> helper class to gain multithread-safe reference-counting.
//2p1 points to an unnamed Foo instance on the heap.
//3In a new scope, p2 is created to point to the same unnamed Foo instance as p1. This copy construction increments the reference-counter maintained inside Foo. Figure 38 shows the pointers at this stage in the processing.

Figure 38 -- Creating a pointer by copy construction

//4bar() is called for the unnamed instance stored in the heap. The displayed address is the same as when p1 was created.
//5When p2 goes out of scope and is destroyed, the reference-counter inside Foo is decremented.

Now another Foo instance and two new pointers are created.

//6p3 points to a new Foo instance on the heap.
//7p4 is created to point to the same Foo instance as p3. Figure 39 shows the pointers at this stage in the processing. Notice that p2 no longer exists.

Figure 39 -- Pointers during the swapWith operation

The swapWith() operation causes two of the pointers to trade bodies.

//8After the swapWith() operation, p4 points to the Foo originally identified by p1, and p1 points to the Foo originally identified by p3. Figure 40 shows the pointers now.

Figure 40 -- Pointers after the swapWith operation

RWTCountedPointer is type-intrusive; your class must implement the reference-counter or inherit from RWTCountingBody. The advantage is that by implementing the reference counter you gain efficiency and have more control over the counter's behavior. If you need a class that is equivalent to RWTCountedPointer but is not type-intrusive, you can use the RWTCountingPointer class.

7.5.3 Using RWTCountingPointer

The RWTCountingPointer<Body,Counter> class is similar to RWTCountedPointer<Body>, except that it doesn't require the body to implement the reference-counter. Because RWTCountingPointer supplies its own reference counting, it can garbage-collect objects that do not directly support reference counting. In particular, unlike RWTCountedPointer, RWTCountingPointer supports primitive data types as bodies.

The reference-counter for RWTCountingPointer is provided by its Counter template parameter. Both the RWSafeCounter and RWUnsafeCounter helper classes can be used as the Counter template parameter. The default is RWSafeCounter, if your compiler supports default template arguments.

You can implement exception-safe aggregation relationships using the RWTCountingPointer template class. When compared to implementations using raw pointers, this technique offers the following advantages:

Consider the UML class diagram in Figure 41, which shows a form of aggregation called composition. Copies of the same aggregate share one instance of its part.

Figure 41 -- Two copies of an aggregate sharing one instance of a part

This form of aggregation is effective when the shared part does not change, or when you need to keep changes to all instances of the aggregate in sync. It does not suit every situation. Keep in mind that if one instance of an aggregate changes a shared part, the change affects all the instances.

An implementation of the aggregation relationship idiom is shown in Example 68. For comparison, the aggregation relationship between A and B is implemented with RWTCountingPointer, while the aggregation relationship between B and C uses a raw pointer. For the complete example, see examples\thr0200osfam\pointer\RWTCountingPointerEx.cpp.

Example 68 -- Implementing an aggregation relationship

//1In this example, the aggregation is established during construction of A, which creates B on the heap. Inside A, dereferencing operations applied to myB_ can be used to access its B. Because the life-cycle of B is dependent on A, this form of aggregation is called composition.
//2Class C plays the same role as class A, but because class C uses a raw pointer, the copy constructor, assignment and destructor implementations are mandatory. Instead of sharing the same B instance, as in class A, the copy constructor allocates another B instance.
//3The construction of a2 doesn't imply a new instance of B. Because of reference-counting, a1 and a2 share the same B instance.
//4The construction of c2 implies a new instance of B.

7.5.3.1 Providing RWTCountingPointer with a Counter

The RWTCounter class is used as the Counter template parameter for RWTCountingPointer<Body,Counter>. RWTCounter is a concrete type derived from the abstract RWTCountingBody. Two predefined typedefs for RWTCounter are available:


Previous fileTop of DocumentContentsIndexNext file

©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.