CoolProgrammer's Linux-Powered Home

ptr.h

// ptr_t<T> defines a "smart pointer"--it automatically counts references
// to the memory it manages and deletes the referenced object when the last
// referring ptr_t is destroyed. Usage of the class has a few restrictions:
//
// Do NOT store pointers it manages separately, UNLESS you can guarantee that
// the referenced object won't accidentally be deleted before you finish with
// the external pointer.
//
// Do NOT store pointers allocated by anything other than new. Along those
// lines, do NOT store arrays with this, since it calls delete and not delete[].
// Using the incorrect deallocation function could very well be a Bad Thing(TM)
//
// Also, somewhere your program must define a global map_t called ptr_map. This
// stores the table of pointer addresses and reference counts.
//
// This template is Copyright (C) 2005 Jeremy Pepper, and is released into the
// public domain AS-IS, without warranty of any kind, express or implied. The
// implementation may well contain undiscovered bugs.

#ifndef PTR_H
#define PTR_H

#include <map>
using namespace std;

typedef map<void *, int> map_t;

extern map_t ptr_map;

template <class T>
class ptr_t {
private:
        T *ptr;
        void cleanup() {
                if(ptr) {
                        ptr_map[ptr]--;
                        if(!ptr_map[ptr]) {
                                ptr_map.erase(ptr);
                                delete ptr;
                        }
                }
        }
public:
        ptr_t() {
                ptr = NULL;
        }
        ptr_t(const T& o) {
                ptr = NULL;
                *this = &o;
        }
        ptr_t(const ptr_t<T> &p) {
                if(this != &p) {
                        ptr = p.ptr;
                        ptr_map[ptr]++;
                }
        }
        ~ptr_t() {
                cleanup();
        }
        T& operator*() const {
                return *ptr;
        }
        T* operator->() const {
                return ptr;
        }
        ptr_t &operator=(const ptr_t &p) {
                if(this != &p) {
                        cleanup();
                        ptr_map[p.ptr]++;
                        ptr = p.ptr;
                }
                return *this;
        }
        ptr_t &operator=(T* p) {
                if(ptr != p) {
                        cleanup();
                        ptr = p;
                        map_t::iterator i = ptr_map.find(ptr);
                        if(i == ptr_map.end())
                                ptr_map[ptr] = 1;
                        else
                                ptr_map[ptr]++;
                }
                return *this;
        }
};

#endif /* PTR_H */
1