Using Counted Pointers

You use ICountedPointerTo almost exactly the same way you use a raw C++ pointer type. The only difference is that you don't have to remember to call addRef and removeRef; the smart pointer does that for you. The ICountedPointerTo equivalent to the first example in Using IMRefCounted is:

class Foo : public IMRefCounted {
    ...
};
...
{
    ICountedPointerTo<Foo> fooPtr = new Foo(); // Calls addRef
    functionCall(fooPtr);
    // removeRef called automatically by fooPtr's destructor
}

The second, copy-on-write example in Using IMRefCounted is a lot simpler using ICountedPointerTo as well:

class Bar {
  public:
    void setValue(int i);
  private:
    ICountedPointerTo<BarImp> fImp;  // BarImp is IMRefCounted
};
void Bar::setValue(int i)
{
    if (fImp->count() > 1) {
         // My implementation is shared, so make my own private copy
         fImp = new BarImp(*fImp);
    }
    fImp->setValue(i);
}

The statement fImp = new BarImp(*fImp); works because ICountedPointerTo's assignment operator is smart enough to call removeRef and addRef on the old and new objects that are pointed to. For details, see the "Assignment and copying" section below.

Use with non-IMRefCounted objects

Sometimes you want to use reference counting on objects of an existing class that does not happen to inherit from IMRefCounted. ICountedPointerTo allows you to do this easily. If the class upon which it is templatized does not inherit from IMRefCounted, ICountedPointerTo adds a reference-counted wrapper around your objects to enable reference counting. For example, the following code will still work even though Foo does not inherit from IMRefCounted:

class Foo {
    ...
};
...
{
    // The ICountedPointerTo constructor will create a
    // reference-counted wrapper around the Foo object.
    ICountedPointerTo<Foo> fooPtr = new Foo(); 
    functionCall(fooPtr);
    // removeRef called automatically by fooPtr's destructor
}

In order for this to work, you must always use ICountedPointerTo rather than raw C++ pointers, to ensure that there is only one wrapper object for each object you want to reference count. The following code will get you into trouble:

ICountedPointerTo<Foo> fooPtr = new Foo();

// Create a raw, "unwrapped" pointer...
Foo *rawPtr = fooPtr.getAlias();

// This line will create a second smart pointer with its own wrapper
// around the Foo object.  This is bad.
ICountedPointerTo<Foo> fooPtr2 = rawPtr;

// This assignment statement will call removeRef on the original
// wrapper, which will cause the Foo object to be deleted.
fooPtr = 0;

// Since the foo object has been deleted, this will crash
fooPtr2->function();

To do this right, simply omit the raw Foo* pointer and use ICountedPointerTo throughout:

ICountedPointerTo<Foo> fooPtr = new Foo();

// Create a second smart pointer that uses the same wrapper.
ICountedPointerTo<Foo> fooPtr2 = fooPtr;

// Calls removeRef on the wrapper, so its count will now be 1
fooPtr = 0;

// The Foo object has not been deleted yet, so this will work
fooPtr2->function();

Assignment and copying methods

All of the ICountedPointerTo constructors and assignment operators do the "right thing" with regard to reference counting. Since this is a fairly tricky subject, each relevant method is described in detail:

Streaming functions

ICountedPointerTo provides streaming operators that let you stream it to and from data streams. Writing an ICountedPointerTo to a stream does not write the pointer itself; it writes the object to which the ICountedPointerTo points. If you stream out several different counted pointers to the same object, the object will only be streamed out the first time, and aliases to it will be streamed out after that. For example:

IDataStream *stream = ....;
ICountedPointerTo<Foo> foo1 = new Foo();
ICountedPointerTo<Foo> foo2 = foo1;
foo1 >>= *stream;    // Streams out the Foo object
foo2 >>= *stream;    // Just streams out an alias
...
ICountedPointerTo<Foo> foo3, foo4;
foo3 <<= *stream;    // Streams in the Foo object
foo4 <<= *stream;    // Creates an alias to the same Foo object
// foo3 and foo4 now point to the same Foo object.

These streaming methods will only work if the object being pointed to inherits from IMStreamable.

Other methods

ICountedPointerTo also provides the usual comparison operators, plus a number of other useful methods:



Using Reference Counted Objects


Counted Pointers
Reference Counted Objects