Главная arrow С++ (часть 3) arrow Большая демонстрационная программа

Большая демонстрационная программа

Программа листинга 2.8 представляет собой более пространный пример, тестирующий все свойства указателя типа GCPtr.
Листинг 2.8. Демонстрация функциональных возможностей класса ocptr
¦include <ioscream> ¦include <new> ¦include "gc.h"
using namespace std;
// Простой класс для тестирования работы указателя типа GCPtr с классами, class MyClass {
int a, republic:
double val;
MyClassO    a = b = 0; }
MyClass(int x, int y)  { a = x; b = y; val = 0.0;
}
-MyClassO { cout « "Destructing MyClass(" « a «       " « b « ")\n";
}
int sum() { return a + b;
}
friend ostream &operator«(ostream &strm, MyClass &obj);
>;
oscream &operator«(ostream &strm, MyClass &obj) strm « "(" « obj.a « " " « obj .b « ")"; return strm;
}
// Передается нормальный указатель функции, void passPtr(inc *p)  {
cout « "Inside passPtr(): " « *p « endl;
}
// Передается указатель типа GCPtr функции, void passGCPtr(GCPtr<int, 0> p)  { cout « "Inside passGCPtr(): " « *p « endl;
}
int main()  { try {
// Объявляется объект GCPtr, указывающий на тип inc. GCPtr<int> ip;
// Размешается объект int и его адрес присваивается ip. ip = new int(22);
// Выводится значение объекта int.
cout « "Value at *ip: " « *ip « "\n\n";.
// Объект ip передается функции. passGCPtr(ip);
// Создается объект ip2 и затем выходит за
// пределы области видимости
{
GCPtr<int> ip2 = ip; }
int *p = ip; // преобразование в указатель типа int * passPtr(p); // передает указатель int * функции paasPtrO
*ip - 100; // присваивает новое значение ip
// Теперь использует неявное преобразование в int * passPtr(ip); cout « endl;
// Создает объект GCPtr, указывающий на массив //из элементов типа int. GCPtr<int, 5> iap = new int[5];
// Инициализирует динамический массив, for(int i=0; i < 5; i++) iap[i] = i;
// Выводит содержимое массива.
cout « "Contents of iap via array indexing.\n"; for(int i=0; i < 5; i++) cout « iapti] « " "; cout « "\n\n";
// Создает итератор int GCiterator. GCPtr<int>::GCiterator itr;
// Теперь использует итератор для доступа к динамически // размещенному массиву.
cout « "Concents of iap via iterator.\n"; for(itr = iap.beginO; itr != iap.endO; itr++)
cout « *itr « " "; cout « "\n\n";
// Генерирует и теряет множество объектов, for(int i=0; l < 10; i++) ip = new int(i+10);
// Теперь вручную собирает мусор с помощью списка для GCPtr<int>. // Помните, что указатели типа GCPtr<int, 5>
//не будут собраны этим вызовом.
cout « "Requesting collection on GCPtr<int> list.Xn"; GCPtr<int>::collect();
// Теперь использует указатель GCPtr, указывающий на объект типа // класса.
GCPtr<MyClass> ob = new MyClass(10, 20);
// Выводит значения с помощью перегруженного блока вывода, cout « "ob points to " « *ob « endl;
// Смена объекта, на который указывает ob. ob = new MyClass(11. 21);
cout « "ob now points to " « *ob « endl;
// Вызов функции-члена с помощью указателя GCPtr. cout « "Sum is : " « ob->sum() « endl;
// Присваивание значения члену класса с помощью указателя GCPtr. ob->val = 19.21;
cout « "ob->val: " « ob->val « "\n\n";
cout « "Now work with pointers to class objects.\n";
// Объявление указателя типа GCPtr на 5-элементный массив // объектов типа MyClass. GCPtr<MyClass.  5> v;
// Размещение массива, v = new MyClass[5];
// Получение итератора MyClass GCiterator. GCPtr<MyClass>::GCiterator mcltr;
// Инициализация массива из элементов типа MyClass. for(int i=0; i<5; i++)  { v[i] = MyClass(i, 2*i);
}
// Вывод содержимого массива из элементов MyClass с помощью // индексирования.
cout « "Cycle through array via array indexing.\n"; for(int i=0; i<5; i++)  { cout « v[i] « " ";
>
cout « "\n\n";
// Вывод содержимого массива из элементов MyClass // с помошью итератора.
cout « "Cycle through array through an iterator.\n"; for(mcItr = v.beginO; mcltr != v.endO; mcltr++)  { cout « *mcltr « " ";
>
cout « "\n\n";
// Другой способ записи предыдущего цикла.
cout « "Cycle through array using a while loop.Xn";
mcltr - v.beginO;
while (mcltr != v.endO) {
cout « *mcltr « " ";
mcltr++;
}
cout « "\n\n";
cout « "mcltr points to an array that is " «   mcltr.size() « " objects long.Xn";
// Находит количество элементов между двумя итераторами. GCPtr<MyClass>: -.GCiterator mcltr2 = v.endO-2; mcltr = v.beginO;
cout « "The difference between mcltr2 and mcltr is "
« mcltr2 - mcltr; cout « "\n\n";
// Можно и так обрабатывать в цикле.
cout « "Dynamically compute length of array.\n";
mcltr = v.beginO;
mcltr2 = v.endO ;
for(int i=0; i < mcltr2 - mcltr; i++) { cout « v[i] « " ";
}
cout « "\n\n";
// Вывод элементов массива в обратном порядке, cout « "Cycle through array backwards.\n"; forOncItr = v.end()-l; mcltr >= v.beginO; mcltr—)
cout « *mcltr « " "; cout « "\n\n";
// Можно, конечно, использовать "нормальный" указатель // для перемещения в массиве.
cout « "Cycle through array using 'normal' pointer\n"; MyClass *ptr = v; for(int i=0; i < 5; i++) cout « *ptr++ « " "; cout « "\n\n";
// Можно обращаться к элементам массива с помощью GCiterator. cout « "Access class members through an iterator.\n"; for(mcItr = v.beginO; mcltr != v.endO; mcltr++)  { cout « mcltr->sum() « " ";
}
cout « "\n\n";
// Можно размещать и удалять указатель на объект GCPtr // обычно, как любой другой указатель, 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";
// Поскольку pp - не указатель для сбора мусора, // его следует удалять вручную, delete рр; } catch(bad_alloc exc)  {
// Реальное приложение может попытаться освободить память
11 с помощью вызова функции collect О, когда возникнет // ошибка при очередном выделении памяти, cout « "Allocation error.\n";
}
return 0;
[алее приводится вывод программы (см. листинг 2.8) с выключенным ре-симом отображения.
alue at *ip:     22*
nside passGCPtrO : 22 inside passPtr (): 22 inside passPtrO : 100
tontents of iap via array indexing. 112 3 4
tontents of iap via iterator. 112 3 4
tequesting collection on GCPtr<int> list.
)b points to (10 20)
>b now points to (11 21)
>um is : 32
>b->val: 19.21
low work with pointers to class objects.
testructing MyClass(0. 0)
testructing MyClass(1, 2)
^structing MyClass(2, 4)
festructing MyClass(3, 6)
festructing MyClass(4, 8)
-Ус1е through array via array indexing.
(0 0)  (1 2)   (2 4)   (3 6)   (4 8)
^cle through array through an iterator. 10 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)
mcltr points to an array that is 5 objects long. The difference between mcltr2 and mcltr 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)
Самостоятельно попробуйте откомпилировать и выполнить программу с включенным режимом отображения (определите макрос DISPLAY В файле gc.h). Внимательно просмотрите программу, сопоставляя строку ее вывода с соответствующим оператором. Это поможет вам лучше понять работу сборщика мусора. Помните, что сбор мусора происходит каждый раз, когда объект GCPtr выходит за пределы области видимости. Такой выход возможен в разных точках программы, таких, например, как возврат в вызывающую программу функции, получившей копию объекта GCPtr в качестве параметра-Не забывайте также о том, что каждый тип объекта GCPtr поддерживает собственный список gclist. Следовательно, сбор мусора в одном списке не вызывает подобного процесса в списках других типов.
 
устройство для сшивания документов, опломбирование дверей