Here is a smart pointer that "knows" the number of existing instances:
smart_ptr.h:
#ifndef _SMART_PTR_H_
#define _SMART_PTR_H_
/*
Keeps track of the number of instantiated pointers
*/
class Reference_counter
{
protected:
typedef unsigned int ValueType;
public:
Reference_counter () : count(0) { } // default constructor
explicit Reference_counter (ValueType c) : count(c) { } // constructor
Reference_counter (const Reference_counter& rc); // copy constructor
Reference_counter& operator= (const Reference_counter& rc); // copy assignment
~Reference_counter () { } // destructor
// modifying member functions
void add_reference () { ++count; } // increments counter, reflecting new pointer creation
bool release (); // decrements counter and check if any pointers left
private:
ValueType count; // counts the number of pointers
};
//-----------------------------------------------------------------------------------------------
/*
Allows multiple pointers to single object. If number of pointers pointing to the same object zero, object deleted.
*/
template <class T>
class Counted_ptr
{
protected:
typedef T* PointerType;
typedef T& ReferenceType;
public:
Counted_ptr(); // default constructor
explicit Counted_ptr(PointerType v); // constructor
Counted_ptr(Counted_ptr<T>& c_ptr); // copy constructor
Counted_ptr<T>& operator= (Counted_ptr<T>& c_ptr); // copy assignment
~Counted_ptr(); // destructor
// modifying member functions
PointerType get() { return value; } // pointee object value access
void reset(PointerType v); // pointer reassignment
PointerType release(); // pointer resources transfer
// access operators
ReferenceType operator* () const { return *value; }
PointerType operator-> () const { return value; }
protected:
void Destroy() { delete value; } // destroy pointee object and free its memory
static PointerType Default() { return nullptr; } // default value for the class StoredType
private:
PointerType value;
Reference_counter* refCount; // If counter = 0; the pointee object is deleted.
};
#include "smart_ptr_def.cpp"
#endif
smart_ptr_def.cpp:
template<class T>
Reference_counter& Reference_counter::operator= (const Reference_counter& rc)
{
if (this == &rc)
{
return *this;
}
count = rc.count;
return *this;
}
//-----------------------------------------------------------------------------------------------
template<class T>
bool Reference_counter::release ()
{
if (!--count)
{
return true;
}
return false;
}
//-----------------------------------------------------------------------------------------------
template<class T>
Counted_ptr<T>::Counted_ptr()
: value(Default()), refCount(nullptr)
{
reCount = new Reference_counter()
refCount->add_reference();
}
//-----------------------------------------------------------------------------------------------
template<class T>
Counted_ptr<T>::Counted_ptr(PointerType v)
: value(v), refCount(nullptr)
{
refCount = new Reference_counter();
refCount->add_reference();
}
//-----------------------------------------------------------------------------------------------
template<class T>
Counted_ptr<T>::Counted_ptr(Counted_ptr<T>& c_ptr)
: value(c_ptr.value), refCount(c_ptr.refCount)
{
refCount->add_reference();
}
//-----------------------------------------------------------------------------------------------
template<class T>
Counted_ptr<T>& Counted_ptr<T>::operator= (Counted_ptr<T>& src)
{
if (this == &src)
{
return *this;
}
if (refCount->release())
{
Destroy();
delete refCount;
}
value = c_ptr.value;
refCount = c_ptr.refCount;
refCount->add_reference();
return *this;
}
//-----------------------------------------------------------------------------------------------
template <class T>
Counted_ptr<T>::~Counted_ptr()
{
if (refCount->release())
{
Destroy();
delete refCount;
}
}
//-----------------------------------------------------------------------------------------------
template <class T>
void Counted_ptr<T>::reset(PointerType v)
{
if (value)
{
Destroy();
}
value = v;
}
//-----------------------------------------------------------------------------------------------
template <class T>
T* Counted_ptr<T>::release()
{
PointerType temp = value;
value = Default();
return temp;
}
main:
#include <iostream>
#include "smart_ptr.h"
int main()
{
Counted_ptr<int> p(new int);
*p.get() = 5;
std::cout <<"p points to: "<< *p << "\n";
int *temp = p.release();
std::cout <<"caller of release(), temp points to: "<< *temp << "\n";
Counted_ptr<int> p2(p);
std::cout <<"copy constructed p2 points to: "<< *p2 << "\n";
Counted_ptr<int> p3(new int(20));
p3 = p2;
std::cout <<"copy assigned p3 points to: "<< *p3 << "\n";
}
Questions:
- Are there any obvious errors that need to be fixed?
- Is the design and structure of the implemented classes good enough?
- What additional feature / functionality (that the generic smart pointer provides) could be added to the above code?