Introduction
Well, I came up with a cool project to try out. This turned out to be a memory manager for C++. Its purpose is to automatically delete heap objects that your application no longer uses. No need to manually delete them. But better yet - it deletes them instantly they are no longer needed. You don't need to wait a specified amount of time for it to delete the objects, nor will it take much processor time to track down all the objects and delete them. This is a simple, yet very functional class. Righty-o, here's the code for the class:
#pragma once
#pragma warning ( disable: 4312 )
template<typename T> class CMemoryManager
{
private:
template<typename T> class Pointer
{
friend class CMemoryManager;
T* p;
DWORD* pdwRefCount;
public:
template<typename Type> void operator = (Type value)
{
*p = value;
}
template<typename Type> bool operator == (Type value)
{
return (*p == value);
}
operator T* () { return p; }
};
Pointer<T> p;
public:
CMemoryManager()
{
Init();
}
CMemoryManager(T* pNew)
{
Init();
SetNewPointer(pNew);
}
CMemoryManager(int val)
{
Init();
SetNewPointer((T*)val);
}
CMemoryManager(const CMemoryManager& rmm)
{
Init();
UpdateMemoryManager(rmm);
}
~CMemoryManager()
{
if (p.pdwRefCount == NULL) return;
if (*p.pdwRefCount == 0 || --(*p.pdwRefCount) == 0)
{
delete p.p;
delete p.pdwRefCount;
Init();
}
}
void Init()
{
p.pdwRefCount = NULL;
p.p = NULL;
}
void AssignNewPointer(const T* pNew)
{
p.p = (T*)pNew;
}
void CheckRefCount()
{
if (p.pdwRefCount == NULL) NewRefCounter();
}
void SetRefCount(DWORD dwNewCount)
{
CheckRefCount();
*p.pdwRefCount = dwNewCount;
}
void IncreaseRefCount()
{
CheckRefCount();
(*p.pdwRefCount)++;
}
void NewRefCounter()
{
p.pdwRefCount = new DWORD;
*p.pdwRefCount = 0;
}
void SetNewPointer(const T* pNew)
{
Delete();
AssignNewPointer(pNew);
IncreaseRefCount();
}
void Delete()
{
this->~CMemoryManager();
Init();
}
void UpdateMemoryManager(const CMemoryManager& rmm)
{
Delete();
AssignNewPointer(rmm.p.p);
p.pdwRefCount = rmm.p.pdwRefCount;
IncreaseRefCount();
}
void operator = (int val)
{
SetNewPointer((T*)val);
}
void operator = (const T* pmm)
{
SetNewPointer(pmm);
}
void operator = (const CMemoryManager* pmm)
{
UpdateMemoryManager(*prmm);
}
void operator = (const CMemoryManager& rmm)
{
UpdateMemoryManager((CMemoryManager&)rmm);
}
void SetNewAddr(T* pNewAddr, DWORD dwRefCount)
{
Delete();
SetNewPointer(pNewAddr);
SetRefCount(dwRefCount);
}
void Detach()
{
if (*p.pdwRefCount == 1)
{
delete p.pdwRefCount;
delete p.p;
}
p.pdwRefCount = NULL;
p.p = NULL;
}
int GetSize() { return sizeof(*p.p); }
Pointer<T>& operator * () { return p; }
T* operator -> () { return p.p; }
operator T* () { return p.p; }
operator void* () { return p.p; }
void operator delete(void* p) { }
T* GetPointer() { return p.p; }
bool operator == (int nCompare) { return (p.p == (T*)nCompare); }
operator bool () { return (p.p != NULL); }
};
#pragma warning ( default: 4312 )
#define pp CMemoryManager
What you simply do, is encapsulate all your heap memory in the CMemoryManager
class. You can then use those pointers as if they were not encapsulated. Or, you are supposed to at least. Try it out! See how it works, and report if anything doesn't work. I don't know if intellisense in Visual Studio 2003 or less will actually detect the class members for the actual pointers, but in 2005, it works perfectly. So, again, try it out, let me know what you think and how it works. No more pesky pointers that you need to delete manually! On a side note, do not use "delete
" on them. Instead, if you want to release the pointer, call the member method Delete
. If the object is no longer in use (reference count is 0), then it is freed. Also remember to always use the container. If you assign a normal pointer to the memory manager, it will not keep the reference count! So, always assign the actual memory manager object, if possible. And lastly, do not use this class to encapsulate memory pointers which are not your responsibility to release. Only use them on memory your own. And, I would recommend that you only use it on newly allocated objects that you allocate yourself.
I've updated the class. It is much more efficient and better now. No bugs as far as I can see.