#ifndef SMARTPTR_H #define SMARTPTR_H ///////////////////////////////////////////////////////////////////// // smartPtr.h - smart pointer used to manage objects and // // ver 1.0 arrays of objects on the heap // // // // Lanaguage: Visual C++, ver 6.0, SP 5.0 // // Platform: Dell Dimension 8100, Win2000, SP 2.0 // // Application: general utility routines, Spring 2002 // // Author: Jim Fawcett, CST 2-187, Syracuse University, // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// /* Module Operations: ================== This module provides a smart pointer class to manage objects and arrays of objects on the heap. Its public interface mimics that of built-in C++ pointers, but it provides for automatic deallocation and bounds checking for access to the referenced objects. Objects of this class can be used to allow STL containers to hold pointers to objects without forcing the user to take over memory management from the container. All smartPtr constructors allocate heap memory for referenced objects. The destructor deallocates. Note that these smartPtrs CAN NOT BE USED FOR POLYMORPHIC operations. Public Interface: ================= smartPtr pDbl; // declare pointer to single object *pDbl = 5.2; smartPtr pDbl(const T &t); // object has initialized value smartPtr pDbl(const T *t, int size); // points to array of doubles T val = *pDbl; // dereference object struct str { int x; double y; char z; } aStr; smartPtr pStr(aStr,4); // declare pointer to array of structures pStr[n]->y = 3.1415; str newStr = pStr[2]; // can read from const smart pointer pDbl1 = pDbl2; // deep assignment (assignment of values) smartPtr pStr2 = pStr; // deep copy construction int n = smartPtr::objectsAllocated(); // inquire about the current allocation smartPtr::verbose(true); // turn on tracing of allocation */ // ///////////////////////////////////////////////////////////////////// // Build Process // ///////////////////////////////////////////////////////////////////// // Required Files: // // smartPtr.h, smartPtr.cpp, trace.h, trace.cpp // // // // Compiler Command: // // cl /GX /DTEST_SMARTPTR smartPtr.cpp trace.cpp // ///////////////////////////////////////////////////////////////////// /* Maintenance History: ==================== ver 1.0 : 24 Feb 02 - first release */ /////////////////////////////////////////////////////////////////////// // definition of smart pointer class specifically for objects on heap // template class smartPtr { public: smartPtr(); smartPtr(const T &t); smartPtr(const T *t, int size); smartPtr(const smartPtr&); ~smartPtr(); smartPtr& operator=(const smartPtr&); T& operator*(); T* operator->(); T& operator[](int n); T operator[](int n) const; unsigned size(); static unsigned objectsAllocated(); static void verbose(bool speak); private: static unsigned numObjectsAllocated; static bool _verbose; int _size; T *_tPtr; }; // /////////////////////////////////////////////////////////////// // initialize static members // //----< store the number of objects currently allocated >------ template unsigned smartPtr::numObjectsAllocated = 0; //----< if true, destructors will announce themselves >-------- template bool smartPtr::_verbose = false; /////////////////////////////////////////////////////////////// // static member functions // //----< return the number of objects currently allocated >----- template unsigned smartPtr::objectsAllocated() { return numObjectsAllocated; } //----< set destructor verbosity >----------------------------- template void smartPtr::verbose(bool speak) { _verbose = speak; } // //----< void constructor allocates a single object on heap >--- template smartPtr::smartPtr() : _size(1) , _tPtr(new T[1]) { ++numObjectsAllocated; }; //----< promotion constructor creates a single object >-------- template smartPtr::smartPtr(const T &t) : _size(1), _tPtr(new T[1]) { *_tPtr = t; ++numObjectsAllocated; } //----< constructs an array of heap-based objects >------------ template smartPtr::smartPtr(const T *t, int size) : _size(size), _tPtr(new T[size]) { for(int i=0; i------------------------------------- template smartPtr::smartPtr(const smartPtr& sp) : _size(sp._size), _tPtr(new T[sp._size]) { for(int i=0; i<_size; i++) _tPtr[i] = sp._tPtr[i]; numObjectsAllocated += _size; } // //----< destructor >------------------------------------------- template smartPtr::~smartPtr() { if(_verbose) { string temp = "deleting "; temp += toString(_size); temp += " objects of type "; temp += typeid(*_tPtr).name(); trace(temp.c_str()); } numObjectsAllocated -= _size; delete [] _tPtr; _tPtr = 0; _size = 0; } //----< return size of array on heap >------------------------- template inline unsigned smartPtr::size() { return _size; } //----< dereference operator >--------------------------------- template inline T& smartPtr::operator*() { return *_tPtr; } //----< selection operator >----------------------------------- template inline T* smartPtr::operator->() { return _tPtr; } //----< index operator >--------------------------------------- template T& smartPtr::operator[](int n) { if(n<0 || _size <= n) throw "index out of domain"; return _tPtr[n]; } //----< index operator for constant objects >------------------ template T smartPtr::operator[](int n) const { if(n<0 || _size >= n) throw "index out of domain"; return _tPtr[n]; } // //----< assignment operator >---------------------------------- template smartPtr& smartPtr::operator=(const smartPtr& sp) { numObjectsAllocated -= _size; _size = sp._size; T *newPtr = new T[_size]; for(int i=0; i<_size; i++) newPtr[i] = _tPtr[i]; delete [] _tPtr; _tPtr = newPtr; numObjectsAllocated += _size; return *this; } #endif