Let's go,Garbage Collector(十一)

来源:互联网 发布:网络4路录像机安装视频 编辑:程序博客网 时间:2024/06/16 22:37

The following program shows a larger example that exercises all of the features of GCPtr:

// Demonstrating GCPtr.
#include <iostream>
#include <new>
#include "gc.h"
using namespace std;
// A simple class for testing GCPtr with class types.
class MyClass {
  int a, b;
public:
  double val;
 
MyClass() { a = b = 0; }
 
MyClass(int x, int y) {
    a = x;
    b = y;
    val = 0.0;
 
}
 
~MyClass() {
    cout << "Destructing MyClass(" <<
         a << ", " << b << ")/n";
  }
 
int sum() {
    return a + b;
  }
 
friend ostream &operator<<(ostream &strm, MyClass &obj);
};
// Create an inserter for MyClass.
ostream &operator<<(ostream &strm, MyClass &obj) {
  strm << "(" << obj.a << " " << obj.b << ")";
  return strm;
}
// Pass a normal pointer to a function.
void passPtr(int *p) {
  cout << "Inside passPtr(): "
       << *p << endl;
}
// Pass a GCPtr to a function.
void passGCPtr(GCPtr<int, 0> p) {
  cout << "Inside passGCPtr(): "
       << *p << endl;
}
int main() {
 
try {
    // Declare an int GCPtr.
    GCPtr<int> ip;
   
// Allocate an int and assign its address to ip.
    ip = new int(22);
   
// Display its value.
    cout << "Value at *ip: " << *ip << "/n/n";
   
// Pass ip to a function
    passGCPtr(ip);
   
// ip2 is created and then goes out of scope 
    {
     GCPtr<int> ip2 = ip;
    }
   
int *p = ip; // convert to int * pointer'
   
passPtr(p); // pass int * to passPtr()
   
*ip = 100; // Assign new value to ip
   
// Now, use implicit conversion to int *
    passPtr(ip);
    cout << endl;
   
// Create a GCPtr to an array of ints
    GCPtr<int, 5> iap = new int[5];
   
// Initialize dynamic array.
    for(int i=0; i < 5; i++)
      iap[i] = i;
   
// Display contents of array.
    cout << "Contents of iap via array indexing./n";
    for(int i=0; i < 5; i++)
     
cout << iap[i] << " ";
    cout << "/n/n";
   
// Create an int GCiterator.
    GCPtr<int>::GCiterator itr;
   
// Now, use iterator to access dynamic array.
    cout << "Contents of iap via iterator./n";
    for(itr = iap.begin(); itr != iap.end(); itr++)
     
cout << *itr << " ";
    cout << "/n/n";
   
// Generate and discard many objects
    for(int i=0; i < 10; i++)
      ip = new int(i+10);
   
// Now, manually garbage collect GCPtr<int> list.
    // Keep in mind that GCPtr<int, 5> pointers
    // will not be collected by this call.
    cout << "Requesting collection on GCPtr<int> list./n";
    GCPtr<int>::collect();
   
// Now, use GCPtr with class type.
    GCPtr<MyClass> ob = new MyClass(10, 20);
   
// Show value via overloaded insertor.
    cout << "ob points to " << *ob << endl;
   
// Change object pointed to by ob.
    ob = new MyClass(11, 21);
    cout << "ob now points to " << *ob << endl;
   
// Call a member function through a GCPtr.
    cout << "Sum is : " << ob->sum() << endl;
   
// Assign a value to a class member through a GCPtr. 
    ob->val = 19.21;
    cout << "ob->val: " << ob->val << "/n/n";
   
cout << "Now work with pointers to class objects./n";
   
// Declare a GCPtr to a 5-element array
    // of MyClass objects.
    GCPtr<MyClass, 5> v;
    // Allocate the array.
    v = new MyClass[5];
   
// Get a MyClass GCiterator.
    GCPtr<MyClass>::GCiterator mcItr;
   
// Initialize the MyClass array.
    for(int i=0; i<5; i++) {
      v[i] = MyClass(i, 2*i);
    }
   
// Display contents of MyClass array using indexing.
    cout << "Cycle through array via array indexing./n"; 
    for(int i=0; i<5; i++) {
     
cout << v[i] << " ";
    }
    cout << "/n/n";
   
// Display contents of MyClass array using iterator. 
    cout << "Cycle through array through an iterator./n"; 
    for(mcItr = v.begin(); mcItr != v.end(); mcItr++) {
     
cout << *mcItr << " ";
    }
    cout << "/n/n";
   
// Here is another way to write the preceding loop. 
    cout << "Cycle through array using a while loop./n"; 
    mcItr = v.begin();
    while(mcItr != v.end()) {
     
cout << *mcItr << " ";
     
mcItr++;
    }
    cout << "/n/n";
   
cout << "mcItr points to an array that is "
         << mcItr.size() << " objects long./n";
   
// Find number of elements between two iterators. 
    GCPtr<MyClass>::GCiterator mcItr2 = v.end()-2;
    mcItr = v.begin();
    cout << "The difference between mcItr2 and mcItr is "
        
<< mcItr2 - mcItr;
    cout << "/n/n";
   
// Can also cycle through loop like this.
    cout << "Dynamically compute length of array./n";
    mcItr = v.begin();
    mcItr2 = v.end();
    for(int i=0; i < mcItr2 - mcItr; i++) {
     
cout << v[i] << " ";
    }
   
cout << "/n/n";
   
// Now, display the array backwards.
    cout << "Cycle through array backwards./n";
    for(mcItr = v.end()-1; mcItr >= v.begin(); mcItr--)
     
cout << *mcItr << " ";
    cout << "/n/n";
   
// Of course, can use "normal" pointer to
    // cycle through array.
    cout << "Cycle through array using 'normal' pointer/n";
    MyClass *ptr = v;
    for(int i=0; i < 5; i++)
     
cout << *ptr++ << " ";
    cout << "/n/n";
   
// Can access members through a GCiterator.
    cout << "Access class members through an iterator./n";
    for(mcItr = v.begin(); mcItr != v.end(); mcItr++) {
     
cout << mcItr->sum() << " ";
    }
    cout << "/n/n";
   
// Can allocate and delete a pointer to a GCPtr
    // normally, just like any other pointer.
    cout << "Use a pointer to a GCPtr./n";
    GCPtr<int> *pp = new GCPtr<int>();
    *pp = new int(100);
    cout << "Value at **pp is: " << **pp;
    cout << "/n/n";
   
// Because pp is not a garbage collected pointer,
    // it must be deleted manually.
    delete pp;
 
} catch(bad_alloc exc) {
    // A real application could attempt to free
    // memory by collect() when an allocation
    // error occurs.
    cout << "Allocation error./n";
 
}
 
return 0;
}

Here is the output with the display option turned off:

Value at *ip: 22
Inside passGCPtr(): 22
Inside passPtr(): 22
Inside passPtr(): 100
Contents of iap via array indexing.
0 1 2 3 4
Contents of iap via iterator.
0 1 2 3 4
Requesting collection on GCPtr<int> list.
ob points to (10 20)
ob now points to (11 21)
Sum is : 32
ob->val: 19.21
Now work with pointers to class objects.
Destructing MyClass(0, 0)
Destructing MyClass(1, 2)
Destructing MyClass(2, 4)
Destructing MyClass(3, 6)
Destructing MyClass(4, 8)
Cycle through array via array indexing.
(0 0) (1 2) (2 4) (3 6) (4 8)
Cycle through array through an iterator.
(0 0) (1 2) (2 4) (3 6) (4 8)
Cycle through array using a while loop.
(0 0) (1 2) (2 4) (3 6) (4 8)
mcItr points to an array that is 5 objects long.
The difference between mcItr2 and mcItr is 3
Dynamically compute length of array.
(0 0) (1 2) (2 4) (3 6) (4 8)
Cycle through array backwards.
(4 8) (3 6) (2 4) (1 2) (0 0)
Cycle through array using 'normal' pointer
(0 0) (1 2) (2 4) (3 6) (4 8)
Access class members through an iterator.
0 3 6 9 12
Use a pointer to a GCPtr.
Value at **pp is: 100
Destructing MyClass(4, 8)
Destructing MyClass(3, 6)
Destructing MyClass(2, 4)
Destructing MyClass(1, 2)
Destructing MyClass(0, 0)
Destructing MyClass(11, 21)
Destructing MyClass(10, 20)

On your own, try compiling and running this program with the display option turned on. (That is, define DISPLAY in gc.h.) Next, walk through the program, matching the output against each statement. This will give you a good feel for the way the garbage collector works. Remember, garbage collection occurs whenever a GCPtr goes out of scope. This happens at various points in the program, such as when a function that receives a copy of a GCPtr returns. In this case, the copy goes out of scope and garbage collection takes place. Also remember that each type of GCPtr maintains its own gclist. Thus, collecting garbage from one list does not cause it to be collected from other types of lists.

 
原创粉丝点击