I made a reference-counting smart pointer class. My aim is to make a "minimal" but "general purpose" smart pointer class with proper documentation. This is basically for educational purposes.
I would like to have comments regarding exception handling, code clarity, comments, ease of use of API, etc. And, also comment if the code is of "industrial level".
#ifndef SMARTPTR_HPP
#define SMARTPTR_HPP
#include <algorithm>
namespace smartptrnamespace
{
//
// Basic reference counting smart pointer (no overloaded Bool magic, etc).
// Ownership of memory on heap is shared amongst objects of this
// class (shared ownership) i.e., no new object of T type is created
// by this class.
// Objects of this class are:
// 1. nothrow-copy-assignable
// 2. nothrow-copy-constructible
// 3. nothrow-destructible, if T is nothrow-destructible
// 4. suitable for storage in a STL container like List, Deque etc.
// Strong exception guarantee
//
// Sample Usage:
// SmartPtr<T> sPtr1 (new T); // sPtr1 refers to object of T type
// SmartPtr<T> sPtr2; // sPtr2 refers to no object
// if (!sPtr2.isAssigned ()) // SmartPtr::isAssigned() returns false if no reference is being held
// cout << "sPtr2 is not holding any reference" << endl;
// sPtr2 = new T; // make a new oject of T and pass ownership to sPtr
//
template<class T>
class SmartPtr
{
public:
// create a new object which is not
// refering to any object on heap.
// no-throw guarantee
explicit SmartPtr ()
: m_pT (NULL),
m_pRefCount (NULL)
{
}
// new object will point to a memory location on heap given by 'pObj'
// Strong exception guarantee
explicit SmartPtr (T *pObj)
: m_pT (pObj),
m_pRefCount (NULL)
{
try
{
m_pRefCount = new int;
}
catch (...)
{
checkedDelete (m_pT);
throw;
}
*m_pRefCount = 1;
}
// new object will refer to same memory on heap as 'rObj'
// no-throw guarantee
SmartPtr (const SmartPtr<T> &rObj)
: m_pT(rObj.m_pT),
m_pRefCount(rObj.m_pRefCount)
{
if (m_pRefCount != NULL)
(*m_pRefCount)++;
}
// make 'rObj' and 'this' will refer to same object on heap
// no-throw guarantee
SmartPtr& operator= (const SmartPtr<T> &rObj)
{
// uses copy-and-swap idiom
this_type(rObj).swap(*this);
return *this;
}
// assign this smart pointer to another object on heap
// Strong exception guarantee
SmartPtr& operator= (T *pTObj)
{
// try and setup memory for reference counter
int *pNewRefCount;
try
{
pNewRefCount = new int;
}
catch (...)
{
delete pTObj;
throw;
}
// stop referring to previous object
updateCountAndTriggerDelete ();
// start referring to new object
m_pRefCount = pNewRefCount;
*m_pRefCount = 1;
m_pT = pTObj;
return *this;
}
// no-throw guarantee
~SmartPtr ()
{
updateCountAndTriggerDelete ();
}
// returns true if this object is holding a reference
// to an object on heap
// no-throw guarantee
bool isAssigned()
{
return !(m_pT == NULL);
}
// no-throw guarantee
T* operator->()
{
return m_pT;
}
// no-throw guarantee
T& operator*()
{
return *m_pT;
}
private:
// make sure we dont delete a incomplete type pointer
// no-throw guarantee
template <class S>
void checkedDelete (S* pSObj)
{
typedef char type_must_be_complete[ sizeof(S)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete pSObj;
}
// count the references and delete it if this is last reference
// no-throw guarantee
void updateCountAndTriggerDelete ()
{
if (m_pRefCount != NULL)
{
(*m_pRefCount)--;
// if this is last reference delete the memory
if (*m_pRefCount == 0)
{
checkedDelete (m_pRefCount);
checkedDelete (m_pT);
}
}
}
// swap the pointer values of 'rObj' with values of 'this'
// no-throw guarantee
void swap (SmartPtr<T> &rObj)
{
std::swap (m_pT, rObj.m_pT);
std::swap (m_pRefCount, rObj.m_pRefCount);
}
// pointer to memory location of object
T *m_pT;
// pointer to memory location where 'reference' count of
// object pointed to by m_pT is kept
int *m_pRefCount;
typedef SmartPtr<T> this_type;
};
} // namespace smartptrnamespace
#endif // SMARTPTR_HPP
updateCountAndTriggerDelete
todecreaseCountAndTriggerDelete
\$\endgroup\$const
in a lot of places : params,isAssigned()
. That would make your code more robust and able to work in more situation. \$\endgroup\$