This is called object pooling in general. Its an optimization that can speed up an algorithm and make its memory use much more efficient if it involves a lot of object creation/deletion. First thing to consider: do you need this optimization??? Don't optimize something that runs with acceptable speed. Optimization can often introduce evil bugs because it makes your code more complex.
If you still insist on pooling your objects: You have to hide the implementation of object creation/deletion of the objects from the code that actually uses the object. The pool is the object that hides this detail.
template <typename T>
class ObjectPool
{
public:
ObjectPool(size_t max_size=100)
: m_MaxSize(max_size)
{}
~ObjectPool()
{
SetMaxPoolSize(0);
}
void SetMaxPoolSize(size_t size)
{
m_MaxSize = size;
size_t current_size = m_Objects.size();
if (current_size > size)
{
for (size_t i=size; i<current_size; ++i)
delete m_Objects[i];
m_Objects.resize(size);
}
}
T* AcquireObject()
{
if (m_Objects.empty())
return new T;
T* obj = m_Objects.back();
m_Objects.pop_back();
return obj;
}
void ReleaseObject(T* obj)
{
if (m_Objects.size() < m_MaxSize)
m_Objects.push_back(obj);
else
delete obj;
}
private:
std::vector<T*> m_Objects;
size_t m_MaxSize;
};
struct S
{
void ObjMethod()
{
printf("%s\n", __FUNCTION__);
}
};
void PoolTest()
{
ObjectPool<S> op;
S* obj = op.AcquireObject();
obj->ObjMethod();
op.ReleaseObject(obj);
}
template <typename T>
class SmartPointerLikeSomethingThatAutomaticallyReleaseTheObject
{
public:
SmartPointerLikeSomethingThatAutomaticallyReleaseTheObject(ObjectPool<T>& pool)
: m_Pool(pool)
{
m_Ptr = pool.AcquireObject();
}
~SmartPointerLikeSomethingThatAutomaticallyReleaseTheObject()
{
Release();
}
void Release()
{
if (m_Ptr)
{
m_Pool.ReleaseObject(m_Ptr);
m_Ptr = NULL;
}
}
T* operator->()
{
assert(m_Ptr);
return m_Ptr;
}
T& operator*()
{
assert(m_Ptr);
return *m_Ptr;
}
private:
SmartPointerLikeSomethingThatAutomaticallyReleaseTheObject(const SmartPointerLikeSomethingThatAutomaticallyReleaseTheObject&);
private:
ObjectPool<T>& m_Pool;
T* m_Ptr;
};
void PoolTestWithRAII()
{
ObjectPool<S> op;
SmartPointerLikeSomethingThatAutomaticallyReleaseTheObject<S> obj(op);
obj->ObjMethod();
{
SmartPointerLikeSomethingThatAutomaticallyReleaseTheObject<S> obj2(op);
obj2->ObjMethod();
}
printf("End of function\n");
}
EDIT: You can also implement a "null pool" that never pools anything, creates the object when you acquire it and it always deletes when you release the object. If you want to switch between a null pool and a normal pool at compile time you can do that with a define, or you can implement a common interface in a null pool and a normal pool if you want to switch between them at runtime.