简单的c++垃圾回收站

下面的程序是我看了<<The Art of C++>>后下来的程序,但运行过后,发现错误很大,所以自己改动了一点,主要是remove()函数的位置错了,并且导致指针p的指向产生问题,所以在此小鉴一下,同时建议大家在阅读这本书的时候,好好注意其中的代码,你会发现有一点错误,同时也强力推荐这本书,很经典!
 
 
 
#include <iostream>
#include <new>
#include "gc.h"
 
using namespace std;
 
int main() {
  GCPtr<int> p;
 
  try {
    p = new int;
  } catch(bad_alloc exc) {
    cout << "Allocation failure!/n";
    return 1;
  }
 
  *p = 88;
 
  cout << "Value at p is: " << *p << endl;
 
  int k = *p;
  cout << "k is " << k << endl;
  
  return 0;
}
#include <iostream>  
#include <list>  
#include <typeinfo>  
#include <cstdlib>
#include <algorithm>  
using namespace std;  
  
// To watch the action of the garbage collector, define DISPLAY.  
 #define DISPLAY  
  
// Exception thrown when an attempt is made to   
// use an Iter that exceeds the range of the   
// underlying object.  
//  
class OutOfRangeExc {  
  // Add functionality if needed by your application.  
};  
  
// An iterator-like class for cycling through arrays  
// that are pointed to by GCPtrs. Iter pointers  
// ** do not ** participate in or affect garbage  
// collection.  Thus, an Iter pointing to  
// some object does not prevent that object  
// from being recycled.  
//  
template <class T> class Iter {  
  T *ptr;   // current pointer value  
  T *end;   // points to element one past end  
  T *begin; // points to start of allocated array  
  unsigned length; // length of sequence  
public:  
  
  Iter() {   
    ptr = end = begin = NULL;  
    length = 0;  
  }  
  
  Iter(T *p, T *first, T *last) {  
    ptr =  p;  
    end = last;  
    begin = first;  
    length = last - first;  
  }  
    
  // Return length of sequence to which this  
  // Iter points.  
  unsigned size() { return length; }  
  
  // Return value pointed to by ptr.  
  // Do not allow out-of-bounds access.
  T &operator*() {   
    if( (ptr >= end) || (ptr < begin) )  
      throw OutOfRangeExc();  
    return *ptr;  
  }  
  
  // Return address contained in ptr.  
  // Do not allow out-of-bounds access.
  T *operator->() {   
    if( (ptr >= end) || (ptr < begin) )  
      throw OutOfRangeExc();  
    return ptr;  
  }    
  
  // Prefix ++.  
  Iter operator++() {  
    ptr++;  
    return *this;  
  }  
  
  // Prefix --.  
  Iter operator--() {  
    ptr--;  
    return *this;  
  }  
  
  // Postfix ++.  
  Iter operator++(int notused) {  
    T *tmp = ptr;  
  
    ptr++;  
    return Iter<T>(tmp, begin, end);  
  }  
  
  // Postfix --.  
  Iter operator--(int notused) {  
    T *tmp = ptr;  
  
    ptr--;  
    return Iter<T>(tmp, begin, end);  
  }  
  
  // Return a reference to the object at the  
  // specified index. Do not allow out-of-bounds  
  // access.  
  T &operator[](int i) {  
    if( (i < 0) || (i >= (end-begin)) )  
      throw OutOfRangeExc();  
    return ptr[i];  
  }  
  
  // Define the relational operators.  
  bool operator==(Iter op2) {  
    return ptr == op2.ptr;  
  }  
  
  bool operator!=(Iter op2) {  
    return ptr != op2.ptr;  
  }  
  
  bool operator<(Iter op2) {  
    return ptr < op2.ptr;  
  }  
  
  bool operator<=(Iter op2) {  
    return ptr <= op2.ptr;  
  }  
  
  bool operator>(Iter op2) {  
    return ptr > op2.ptr;  
  }  
  
  bool operator>=(Iter op2) {  
    return ptr >= op2.ptr;  
  }  
  
  // Subtract an integer from an Iter.  
  Iter operator-(int n) {  
    ptr -= n;  
    return *this;  
  }  
  
  // Add an integer to an Iter.  
  Iter operator+(int n) {  
    ptr += n;  
    return *this;  
  }  
  
  // Return number of elements between two Iters.  
  int operator-(Iter<T> &itr2) {  
    return ptr - itr2.ptr;  
  }  
    
};  
  
  
// This class defines an element that is stored  
// in the garbage collection information list.   
//  
template <class T> class GCInfo {  
public:  
  unsigned refcount; // current reference count
 
  T *memPtr; // pointer to allocated memory  
  
  /* isArray is true if memPtr points  
     to an allocated array. It is false  
     otherwise. */  
  bool isArray; // true if pointing to array  
  
  /* If memPtr is pointing to an allocated  
     array, then arraySize contains its size */  
  unsigned arraySize; // size of array  
  
  // Here, mPtr points to the allocated memory.
  // If this is an array, then size specifies
  // the size of the array.  
  GCInfo(T *mPtr, unsigned size=0) {  
    refcount = 1;
    memPtr = mPtr;  
    if(size != 0)  
      isArray = true;  
    else  
      isArray = false;  
  
    arraySize = size;  
  }
 
};  
  
// Overloading operator== allows GCInfos to be compared.  
// This is needed by the STL list class.   
template <class T> bool operator==(const GCInfo<T> &ob1,  
                const GCInfo<T> &ob2) {  
  return (ob1.memPtr == ob2.memPtr);  
}  
  
  
// GCPtr implements a pointer type that uses  
// garbage collection to release unused memory.  
// A GCPtr must only be used to point to memory  
// that was dynamically allocated using new.   
// When used to refer to an allocated array,  
// specify the array size.  
//  
template <class T, int size=0> class GCPtr {  
 
  // gclist maintains the garbage collection list.  
  static list<GCInfo<T> > gclist;  
 
  // addr points to the allocated memory to which  
  // this GCPtr pointer currently points.  
  T *addr;  
  
  /* isArray is true if this GCPtr points  
     to an allocated array. It is false  
     otherwise. */  
  bool isArray; // true if pointing to array  
  
  // If this GCPtr is pointing to an allocated  
  // array, then arraySize contains its size.  
  unsigned arraySize; // size of the array  
 
  static bool first; // true when first GCPtr is created
 
  // Return an interator to pointer info in gclist.  
  typename list<GCInfo<T> >::iterator findPtrInfo(T *ptr);
 
public:  
  
  // Define an iterator type for GCPtr<T>.  
  typedef Iter<T> GCiterator;  
  
  // Construct both initialized and uninitialized objects.  
  GCPtr(T *t=NULL) {
 
    // Register shutdown() as an exit function. 
    if(first) atexit(shutdown);
    first = false;
 
    list<GCInfo<T> >::iterator p;
 
    p = findPtrInfo(t);
 
    // If t is already in gclist, then
    // increment its reference count. 
    // Otherwise, add it to the list.
    if(p != gclist.end()) 
      p->refcount++; // increment ref count
    else {
      // Create and store this entry.  
      GCInfo<T> gcObj(t, size);  
      gclist.push_front(gcObj);  
    }
 
    addr = t;  
    arraySize = size;  
    if(size > 0) isArray = true;  
    else isArray = false;  
    #ifdef DISPLAY  
      cout << "Constructing GCPtr. ";  
      if(isArray)   
        cout << " Size is " << arraySize << endl;  
      else  
        cout << endl;  
    #endif  
  }  
  
  // Copy constructor.  
  GCPtr(const GCPtr &ob) {  
    list<GCInfo<T> >::iterator p;
 
    p = findPtrInfo(ob.addr); 
    p->refcount++; // increment ref count
  
    addr = ob.addr;  
    arraySize = ob.arraySize;  
    if(arraySize > 0) isArray = true;  
    else isArray = false;  
    #ifdef DISPLAY  
      cout << "Constructing copy.";  
      if(isArray)   
        cout << " Size is " << arraySize << endl;  
      else  
        cout << endl;  
    #endif  
  }  
  
  // Destructor for GCPTr. 
  ~GCPtr();  
  
  // Collect garbage.  Returns true if at least  
  // one object was freed.  
  static bool collect(); 
     
  // Overload assignment of pointer to GCPtr.  
  T *operator=(T *t); 
 
  // Overload assignment of GCPtr to GCPtr.  
  GCPtr &operator=(GCPtr &rv); 
 
  // Return a reference to the object pointed  
  // to by this GCPtr.  
  T &operator*() {  
    return *addr;  
  }  
  
  // Return the address being pointed to.  
  T *operator->() { return addr; }    
  
  // Return a reference to the object at the  
  // index specified by i.  
  T &operator[](int i) {  
    return addr[i];  
  }  
  
  // Conversion function to T *.  
  operator T *() { return addr; }  
  
  // Return an Iter to the start of the allocated memory.  
  Iter<T> begin() {  
    int size;  
  
    if(isArray) size = arraySize;  
    else size = 1;  
  
    return Iter<T>(addr, addr, addr + size);  
  }      
  
  // Return an Iter to one past the end of an allocated array.  
  Iter<T> end() {  
    int size;  
  
    if(isArray) size = arraySize;  
    else size = 1;  
  
    return Iter<T>(addr + size, addr, addr + size);  
  }  
  
  // Return the size of gclist for this type  
  // of GCPtr.  
  static int gclistSize() { return gclist.size(); }  
  
  // A utility function that displays gclist.  
  static void showlist(); 
 
  // Clear gclist when program exits. 
  static void shutdown(); 
};  
  
// Creates storage for the static variables
template <class T, int size>   
  list<GCInfo<T> > GCPtr<T, size>::gclist; 
 
template <class T, int size> 
  bool GCPtr<T, size>::first = true; 
 
// Destructor for GCPtr. 
template <class T, int size> 
GCPtr<T, size>::~GCPtr() {  
  list<GCInfo<T> >::iterator p;  
  
  p = findPtrInfo(addr);
  if(p->refcount) p->refcount--; // decrement ref count
 
  #ifdef DISPLAY  
    cout << "GCPtr going out of scope./n";
  #endif  
 
  // Collect garbage when a pointer goes out of scope.
  collect();  
  
  // For real use, you might want to collect  
  // unused memory less frequently, such as after  
  // gclist has reached a certain size, after a  
  // certain number of GCPtrs have gone out of scope,  
  // or when memory is low.  
}  
 
// Collect garbage.  Returns true if at least  
// one object was freed.  
template <class T, int size> 
bool GCPtr<T, size>::collect() {   
  bool memfreed = false;  
     
  #ifdef DISPLAY  
    cout << "Before garbage collection for ";  
    showlist();  
  #endif  
 
  list<GCInfo<T> >::iterator p;
 
  do {  
  
    // Scan gclist looking for unreferenced pointers.  
    for(p = gclist.begin(); p != gclist.end(); p++) {  
      // If in-use, skip.
      if(p->refcount > 0) continue;  
 
      memfreed = true;  
    
      if(p->memPtr) cout << "   " << *p->memPtr;  
      else cout << "   ---";  
      cout << endl;
   
   
 
       //cout << "   " << *p->memPtr;    
      // Remove unused entry from gclist.
    
    
    
      // Free memory unless the GCPtr is null.
      if(p->memPtr) {
        if(p->isArray) {  
          #ifdef DISPLAY  
            cout << "Deleting array of size "  
                 << p->arraySize << endl;  
          #endif  
          delete[] p->memPtr; // delete array  
          
  }  
        else {  
          #ifdef DISPLAY  
            cout << "Deleting: "  
                 << *(T *) p->memPtr << "/n";  
          #endif
   
          delete p->memPtr;// delete single element  
       
   
  }  
      }
 
      // Restart the search.
     break;
    }
   gclist.remove(*p);
    p = gclist.begin();
  } while(p != gclist.end()); 
  
  #ifdef DISPLAY  
    cout << "After garbage collection for ";  
    showlist();  
  #endif  
  
  return memfreed;  
}  
 
// Overload assignment of pointer to GCPtr.  
template <class T, int size> 
T * GCPtr<T, size>::operator=(T *t) {  
  list<GCInfo<T> >::iterator p;  
  
  // First, decrement the reference count
  // for the memory currently being pointed to.
  p = findPtrInfo(addr);
  p->refcount--; 
 
  // Next, if the new address is already
  // existent in the system, increment its
  // count.  Otherwise, create a new entry
  // for gclist.
  p = findPtrInfo(t);
  if(p != gclist.end()) 
    p->refcount++; 
  else {
    // Create and store this entry.  
    GCInfo<T> gcObj(t, size);  
    gclist.push_front(gcObj);  
  }
 
  addr = t; // store the address.  
  
  return t;  
}
 
// Overload assignment of GCPtr to GCPtr.  
template <class T, int size> 
GCPtr<T, size> & GCPtr<T, size>::operator=(GCPtr &rv) {  
  list<GCInfo<T> >::iterator p;  
 
  // First, decrement the reference count
  // for the memory currently being pointed to.
  p = findPtrInfo(addr);
  p->refcount--;
 
  // Next, increment the reference count of
  // the new address.
  p = findPtrInfo(rv.addr);
  p->refcount++; // increment ref count
 
  addr = rv.addr;// store the address.  
 
  return rv;  
}  
 
// A utility function that displays gclist.  
template <class T, int size> 
void GCPtr<T, size>::showlist() {  
  list<GCInfo<T> >::iterator p;  
  
  cout << "gclist<" << typeid(T).name() << ", "  
       << size << ">:/n";  
  cout << "memPtr      refcount    value/n";  
      
  if(gclist.begin() == gclist.end()) {  
    cout << "           -- Empty --/n/n";  
    return;  
  }  
   
  for(p = gclist.begin(); p != gclist.end(); p++) {  
    cout <<  "[" << (void *)p->memPtr << "]"
         << "      " << p->refcount << "     ";  
    if(p->memPtr) cout << "   " << *p->memPtr;  
    else cout << "   ---";  
    cout << endl;        
  }  
  cout << endl;  

 
// Find a pointer in gclist.
template <class T, int size> 
typename list<GCInfo<T> >::iterator 
  GCPtr<T, size>::findPtrInfo(T *ptr) {  
 
  list<GCInfo<T> >::iterator p;  
  
  // Find ptr in gclist.  
  for(p = gclist.begin(); p != gclist.end(); p++) 
    if(p->memPtr == ptr) 
      return p;
 
  return p;  
}  
 
// Clear gclist when program exits. 
template <class T, int size>  
void GCPtr<T, size>::shutdown() { 
 
  if(gclistSize() == 0) return; // list is empty
 
  list<GCInfo<T> >::iterator p; 
 
  for(p = gclist.begin(); p != gclist.end(); p++) { 
    // Set all reference counts to zero 
    p->refcount = 0; 
  }
 
测试程序:
  #ifdef DISPLAY     
    cout << "Before collecting for shutdown() for " 
         << typeid(T).name() << "/n";   
  #endif 
 
  collect(); 
 
  #ifdef DISPLAY     
    cout << "After collecting for shutdown() for " 
         << typeid(T).name() << "/n";   
  #endif 
}
 
 
#include <iostream>
#include <new>
#include "gc.h"
 
using namespace std;
 
int main() {
  GCPtr<int> p;
 
  try {
    p = new int;
  } catch(bad_alloc exc) {
    cout << "Allocation failure!/n";
    return 1;
  }
 
  *p = 88;
 
  cout << "Value at p is: " << *p << endl;
 
  int k = *p;
  cout << "k is " << k << endl;
  
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值