Local Pointers

Introduction

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.

Main Idea

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 Implementation

Memory Management

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;
   }

Actual Class Definition

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;
};

Complete Program

For a complete program demonstrating safe pointers click here .