|
Back in the 90ies, when i was writing for MFC and its data types, and when STL was not well supportd by Visual Studio 6,
I wrote my own smart pointer for reference counting and RAII. It should support COM objects, but unlike the ComQIPtr
class, without using Microsoft specific language features.
Today i'm still using this class as it has proven to work well and contains save methods for common usage, but still
provides low level access to the managed pointer if needed, like TakeOver(.), Expose(.), etc.
|
|
|
|
These images explain the difference:
|
|
|
A Pointer points to something,
but the target can go away.
|
|
A Reference holds something.
The target cannot go away so easily.
|
|
Since the programming language C++ provides only a pointer,
I have written my own reference data type.
(What C++ calls reference is actually an
alias: it's another name for a variable.)
The idea of a reference is not new. Many languages have
them and there exist smart pointers for C++. You have to
chose if you like my smart pointer or another one.
|
|
|
What is the ref class?
|
|
The ref class
is a smart pointer. This means it is a class that acts like
a pointer but has additional functionality. You can use the
ref class instead
of C pointers and forget about calling
AddRef() and
Release().
It is not only a matter of comfort. It also helps to create
safe code:
-
If you otherwise would forget to delete an object
(memory leak) the ref
class automatically does this. Because when a
ref object
goes out of scope the compiler destructs it, and this
results in Release()
being called on the object the ref object
points to.
-
This even happens if you, or another programmer later
adds a return
statement, or a break
or continue statement
to a function.
In this situation it is easy to forget to deinitialize a former
created object.
-
It automatically calls
AddRef() and
Release() as
apropriate when you assign a pointer or another
ref pointer
to a ref pointer.
You cannot forget to call these functions.
And it provides for clearer code. E.g.
you just say that you want to store an adress
of an object. The code only contains the assignment,
but no if(pFoo)
Release(pFoo); and if(pFoo)
AddRef(pFoo); line before and after the assignment,
which would prevent people from seeing the essence of
what the code does - the assignment.
|
|
|
What are its capabilities?
|
|
The ref class
can be used with COM objects as well as with your own
classes. To use the ref pointer
with your own classes, add the methods AddRef()
and Release() to your class.
They can look like void AddRef() { mRefCount++; }
and void Release() { if(!--mRefCnt) delete this; }
There is no need to have a return value. mRefCnt
should be a member variable of the class and be initialized to 0 in the constructor.
If the _COM macro is #defined, there are some
additional methods that replace
CoCreateInstance(.)
and QueryInterface(.).
There are also methods for passing a ref pointer
between threads. They replace CoMarshalInterThreadInterfaceInStream(.)
and its friend.
Some methods on the ref class
itself allow for advanced uses. E.g. the SplittOff(.)
method calls AddRef() and returns
the adress of the target object. Or the Expose()
method allows to access the internally maintained pointer.
|
|
|
How to use it?
|
|
Instead of
CSpaceShip* pShip= new CSpaceShip(args);
write
ref<CSpaceShip> refShip= new CSpaceShip(args);
and forget about deleting pShip.
Instead of
CSpaceShip* pMyShip= pShip;
if(pMyShip) pMyShip->AddRef();
write
ref<CSpaceShip> refMyShip= refShip;
and forget about calling AddRef() and Release().
Instead of
pMyShip->Swim(args);
write
refMyShip->Swim(args);
no real difference.
|
|
|
Where to get it?
|
|
The ref pointer is
contained in the ref.h file. There is no ref.cpp file.
There is a comment on the beginning of that file. Please keep it
intact. It contains credit information and tells where to get the
latest version.
|
|
|