Introduction
A reference-based object must be managed with consideration to memory allocation and de-allocation. A garbage collector and smart-pointer helps us avoid these annoying considerations.
But, a standard C++ compiler has no garbage collector. And, in spite of some libraries implementing a smart-pointer, a C++ compiler has no reference count for an object, so the compiler can't manage the object's scope within functions.
TheCRefObject
is not just a smart pointer, it supports and manages reference information of objects. So you can passCRefObject
to a function and return from that function. In any scope, if you keep theCRefObject
instance, its object is never destroyed.
Also, when you want to store different types of objects in one container likeClassA
andClassB
, what can you do? UsingCSessionObject
you can do this without any additional work. Just reference the container with an Object-Key and you can store and retrieve these objects from the container.
Background
CRefObject
uses a technique implemented inCString
.CRefObject
allocates a memory block for an object as an unknown memory block followed byCObjectData
.CObjectData
has information for managing the reference counter.
This method has many advantages - it prevents defragmenting memory byCObjectData
.
class _TAllocator :public T {public:void* PASCALoperatornew(size_t nSize) { LPVOID pNewObj =newBYTE[nSize +sizeof(CObjectData)] ;return ((BYTE*)pNewObj) +sizeof(CObjectData) ;}void PASCALoperatordelete(void* p) {delete [] (((CObjectData*)p) -1) ;}} ;
If you wish to know more about the principle behindCRefObject
, look at theCString
source code.
CSessionObject
started from the question 'How can I store all ofCRefObject
objects in onestd::map
class?'. Because STL is based on templates, if I want to use these I must define an explicit parameterized Type. However,CRefObject
is also template based, so I can't do it.
I thought about it, and had an idea!
CRefObject
doesn't manage a real object. It just manages unknown memory blocks. So, I decided to store these memory blocks instd::map
.
CSessionObject
represents an explicit Session object usingCRefObject
. You can modifyCRefObject
, but I didn't want to do that. So, I wrote another class.CManagedObjData
is a bridge to manage the reference count withinCObjectData
andCSessionObject
.CSession
is the container which stores and retrieves Objects by the Key.
The download project also has a C++ Unit Test. I wrote some unit test routines based onCPPUnit Lite. The DLL must have a Test Entry Point.
// Copy this and paste to your codeextern"C" {__declspec(dllexport)void TestEntryPoint() { TestResult tr; TestRegistry::runAllTests(tr); }}
TestLoader.EXE loads the DLL and executes its Test Entry Point. You can findTestLoader.EXE in my Zip files, not in the CPPUnit Lite.TestLoader.EXE is written by me.
TestLoader.EXE xXx.DLL
If you use Visual Studio, use like this:

This is my setting, you must adapt it for your environment.
Using the code
First, you need to define a parameterized class.
typedef CRefObject<_TWorkspaceValue> CWorkspaceValue ;
CRefObject
has no constructor for baseType
. So, if you define it like this, no object will be created.
CWorkspaceValue WorkspaceValue ;
If you want to create a new instance for the object, you must define it like this:
CWorkspaceValue WorkspaceValue(NULL) ;
Finally, you can use this object just like a value object. No need to worry about memory management.
Do you want to assign this to a new one? Look at this:
CWorkspaceValue AnotherValue(WorkspaceValue) ;CWorkspaceValue Others ;Others = WorkspaceValue ;
AnotherValue
,Others
andWorkspaceValue
share one object -WorkspaceValue
. If you change an object's value from any one of them, it affects all of them.
To prevent this, you'd better useLock
.
Others.Lock() ;Others->Value = NewValue ;Others.Unlock() ;
Lock()
method creates a new object. It works like aCString::Lock()
.
You can create a new instance from base type.
_TWorkspaceValue BaseType ;BaseType.Value = NewValue ;CWorkspaceValue v1(&BaseType) ;Others = &BaseType ;
In function parameter and return value, you can use this like valued-object, but it works as a ref-object. No value copy, just counts a reference counter.
CWorkspaceValue GetWorkspace(LPCSTR szWorkspaceName){return m_WsList[szWorkspaceName] ;}void InsertItem(CWorkspaceValue NewValue){ m_WsList[NewValue->WorkspaceName] = NewValue ;}
If you want to reference base type, use the->
operator.
For more information aboutCSessionObject
, you'd better referenceRefObject.cpp in the Zip file.
Just what I say is,CSessionObject
is compatible withCRefObject
:).
History
- 06/10/2005 - Fixed 'SessionObject.h'. It reports a compile error when compiled with another project that uses 'SessionObject.h'.