You have been using counted pointers since the begining of the semester. These pointers not only manage memory (prevent memory leaks), they minimize memory use by reusing a pointer if it is copied or sent to a method.. A simpler form a pointer that also provideds protection against memory leaks, but is not as efficient when using memory is presented here.
The class SafePtr is a simple envelope class which raps a pointer inside an object that is responsible for copying, and deleting it. In all such cases, you must create a destructor, copy constructor, and assignment statement. Because this class has the responsiblity of replacing the primitive pointer type, you must override the basic pointer operators *, -> and void (used to test if the pointer is null).
The main constructor builds a SafePtr from a pointer of the type it contains.
template < class Type>
SafePtr< Type>::SafePtr(Type *p = NULL)
{
data = p;
}
The destructor should delete the memory allocated for the safe pointer, so it is a very simple function.
SafePtr::~SafePtr()
{
if (data)
delete data;
}
Both the copy constructor and the assigment operator have to preserve the data if the parameter or variable that is assigned the pointer is deleted. This means that a new pointer is allocated in each of these functions. In addition, the assignment operator must make sure that it destroys the current pointer stored in the object while avoiding self-destruction when a pointer is assigned to itself. To avoid self-destruction, a new pointer is created and the data is transferred before the old pointer is destroyed.
template < class Type>
SafePtr< Type>::SafePtr(const SafePtr< Type> &s)
{
if(s.data)
{
data = new Type;
*data = *(s.data);
}
else
data = NULL;
}
template < class Type>
SafePtr& SafePtr< Type>::operator = (const SafePtr &s)
{
if(s.data)
{
Type *temp = new Type;
*temp = *s; //make sure that if s is this, don't delete s
}
else
temp = NULL;
if (data) //if there is currently memory allocated, delete it
delete data;
data = temp;
return *this;
}
template < class Type>
class SafePtr
{
public:
SafePtr(Type *p = NULL){data = p; }
SafePtr(const SafePtr< Type> &s){
/*cout<<"Entering copy constructor"<< endl;*/
if(s.data){data = new Type; *data = *(s.data);}
else data = NULL;}
~SafePtr(){
/*cout<<"Entering destructor"<< endl;*/
if (data)
delete data;}
SafePtr& operator = (const SafePtr &s)
{
Type *temp;
if (s.data)
{
temp = new Type;
*temp = *s; //make sure that if s is this, don't delete s
}
else
temp = NULL;
if (data)
delete data;
data = temp;
return *this;
}
Type* operator ->(){ return data;}
Type& operator*() {return *data;}
Type* operator ->()const { return data;}
Type& operator*()const{ return *data;}
operator const void*() const {return data ? this : 0;}
private:
Type * data;
};
For a complete program demonstrating safe pointers click here .